jmap的使用以及内存溢出分析

jmap的使用以及内存溢出分析jmap 的使用以及内存溢出分析 jmap java 内存映像工具 jmap MemoryMapfor 命令用于生成堆转储快照 一般称为 heapdump 或 dump 文件 还有几种方式获取 dump 文件 使用 JVM 参数选项 XX HeapDumpOnOu 参数 可以让虚拟机在 OOM 异常出现之后自动生成 dump 文件 通过 XX HeapDumpPath path 设置 dump 文件路径 有时候 dump 文件比较大的时候可能无法自动导出 这时候就需要使用 jmap dump 手动导

jmap的使用以及内存溢出分析

jmap(java内存映像工具)

jmap(Memory Map for Java)命令用于生成堆转储快照(一般称为heapdump或dump文件)。还有几种方式获取dump文件:使用JVM参数选项-XX:+HeapDumpOnOutOfMemoryError参数,可以让虚拟机在OOM异常出现之后自动生成dump文件,通过-XX:HeapDumpPath=path 设置dump文件路径(有时候dump文件比较大的时候可能无法自动导出,这时候就需要使用jmap -dump手动导出了);通过-XX.+HeapDumpOnCtrlBreak参数则可以使用[Ctrl]+[Break]键让虚拟机生成dump文件;或者在Linux系统下通过Kill -3命令发送进程退出信号,也能拿到dump文件。

jmap的作用并不仅仅是为了获取dump文件,它还可以查询finalize执行队列、Java堆和永久代的详细信息,如空间使用率、当前用的是哪种收集器等。和jinfo命令一样,jmap有不少功能在Windows平台下都是受限的,除了生成dump文件的-dump选项和用于查看每个类的实例、空间占用统计的-histo选项在所有操作系统都提供之外,其余选项都只能在Linux/Solans下使用。官方文档地址

1.1、查看内存使用情况

[root@localhost /]# jmap -heap 9906 Attaching to process ID 9906, please wait... Debugger attached successfully. Server compiler detected. JVM version is 25.221-b11 using thread-local object allocation. Mark Sweep Compact GC Heap Configuration: MinHeapFreeRatio = 40 MaxHeapFreeRatio = 70 MaxHeapSize =  (944.0MB) NewSize =  (20.0MB) MaxNewSize =  (314.625MB) OldSize =  (40.0MB) NewRatio = 2 SurvivorRatio = 8 MetaspaceSize =  (20.MB) CompressedClassSpaceSize =  (1024.0MB) MaxMetaspaceSize = 415 MB G1HeapRegionSize = 0 (0.0MB) Heap Usage: New Generation (Eden + 1 Survivor Space): capacity =  (18.0625MB) used =  (5.0844MB) free =  (12.0156MB) 28.046% used Eden Space: capacity =  (16.0625MB) used =  (4.8125MB) free =  (11.1875MB) 28.681% used From Space: capacity =  (2.0MB) used =  (0.17188MB) free =  (1.82812MB) 25.5938% used To Space: capacity =  (2.0MB) used = 0 (0.0MB) free =  (2.0MB) 0.0% used tenured generation: capacity =  (40.0MB) used =  (34.094MB) free =  (5.90625MB) 86.734% used 31688 interned Strings occupying  bytes. 

1.2、查看内存中对象数量及大小

#查看所有对象,包括活跃以及非活跃的 jmap -histo <pid> | more #查看活跃对象 jmap -histo:live <pid> | more [root@localhost /]# jmap -histo:live 9906 | more num #instances #bytes class name ---------------------------------------------- 1: 72627  [C 2: 12052  [I 3: 3709  [B 4: 71294  java.lang.String 5: 14306  java.lang.reflect.Method 6: 8153  java.lang.Class 7: 26390  java.util.HashMap$Node 8: 23271  java.util.concurrent.ConcurrentHashMap$Node 9: 10490  [Ljava.lang.Object; 10: 5128  [Ljava.util.HashMap$Node; #对象说明 B byte C char D double F float I int J long Z boolean [数组,如[I表示int[] [L+类名 其他对象 

1.3、将内存使用情况dump到文件中

#用法: jmap -dump:format=b,file=dumpFileName <pid> #示例 [root@localhost /]# jmap -dump:format=b,file=/cfile/dump.dat 9906 Dumping heap to /cfile/dump.dat ... Heap dump file created 

在这里插入图片描述

1.4、通过jhat对dump文件进行分析

jvm的内存dump到文件中,这个文件是一个二进制的文件,不方便查看,可以借助于jhat工具进行查看。

#用法: jhat -port <port> <file> #示例 [root@localhost cfile]# jhat -port 8888 /cfile/dump.dat Reading from /cfile/dump.dat... Dump file created Thu Aug 19 11:31:02 CST 2021 Snapshot read, resolving... Resolving  objects... Chasing references, expect 95 dots............................................................................................... Eliminating duplicate references............................................................................................... Snapshot resolved. Started HTTP server on port 8888 Server is ready. 

打开浏览器进行访问:ip+端口(8888)
在这里插入图片描述

在最后面有OQL查询功能。

在这里插入图片描述

进入页面,输入下面语句查询字符串大于10000,点击Execute按钮,查询结果:

select s from java.lang.String s where s.value.length >= 10000 

在这里插入图片描述

2、通过MAT工具对dump文件进行分析(官网)

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I9geT1sO-1629355535351)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819114901423.png)]

2.1、下载安装

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V7GQluyM-1629355535352)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819134930028.png)]

运行独立版 Memory Analyzer 所需的最低 Java 版本是 Java 11 如果本地安装的JDK是更低版本的可以下载旧版本。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N61htSA0-1629355535352)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819140452413.png)]

下载完成后解压MemoryAnalyzer-1.8.1.-win32.win32.x86_64.zip,解压后如图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OU9rJl0G-1629355535353)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819140912714.png)]

2.2、使用方式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看对象以及它的依赖:


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1WdBhgpu-1629355535355)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819141903120.png)]

查看可能存在内存泄露的分析:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HSgNBWKc-1629355535355)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819142008106.png)]

3、内存溢出的定位与分析

引起内存溢出的原因有很多种,常见的有以下几种:

  • 内存中加载的数据量过于庞大,如一次从数据库取出过多数据。
  • 集合类中有对对象的引用,使用完后未清空,使得JVM不能回收。
  • 代码中存在死循环或循环产生过多重复的对象实体。
  • 使用的第三方软件中的BUG。
  • 启动参数内存值设定的过小。

内存溢出在实际的生产环境中经常会遇到,如,不断的将数据写入到一个集合中,出现了死循环或者读取超大的文件等等,都可能会造成内存溢出。如果出现了内存溢出,首先我们需要定位到发生内存溢出的环节,并且进行分析,是正常还是非正常情况,如果是正常的需求,就应该考虑加大内存的设置,如果是非正常需求,那么就要对代码进行修改,修复这个bug。

3.1、模拟内存溢出

import java.util.ArrayList; import java.util.List; import java.util.UUID; public class TestJvmOutOfMemory { 
    public static void main(String[] args) { 
    List<Object> list = new ArrayList<>(); for (int i = 0; i < ; i++) { 
    String str = ""; for (int j = 0; j < 1000; j++) { 
    str += UUID.randomUUID().toString(); } list.add(str); } System.out.println("ok"); } } 

为了更快的现实效果,这里使用Idea,设置执行的参数

#在每次发生内存溢出时,JVM会自动将堆转储,dump文件存放在-XX:HeapDumpPath指定的路径下。 -Xms8m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D: 

在这里插入图片描述

测试结果如下:

在这里插入图片描述
导入到MAT工具中进行分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N0a7OZ1h-1629355535357)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819144134395.png)]
可以看到,有87.02%的内存由Object[]数组占有,所以比较可疑。


分析:已经有超过87%的内存都被它占有,这种情况是非常有可能出现内存溢出的

查看详情:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4da6MWYn-1629355535358)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20210819144329342.png)]
可以看到集合中存储了大量的uuid字符串。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/231529.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号