如何分析巨大的 Java heap dump

当要分析一个很大的jvm heap dump时,比如说20多G,从服务器下载下来就需要很久,还要考虑自己主机的内存够不够。

Eclipse Memory Analyzer(MAT)可以用来完成这件令人头疼的事,这里我们不使用Eclipse的UI,直接使用MAT提供的一个脚本来解析heap dump,生成HTML文件的报告,这些报告可以下载到本地或者通过web服务器来浏览。如果是64位的CentOS操作系统,通过如下地址下载MAT:
Linux (x86_64/GTK+)

下载之后,直接解压,接入解压目录,有一个配置文件MemoryAnalyzer.ini,更改配置文件,设置一个比较大的heap以便能够加载dump:

1
2
3
4
5
6
7
-startup
plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.100.v20110505
-vmargs
-Xms30g
-Xmx30g

运行MAT来分析具体的heap dump:

1
./ParseHeapDump.sh ../heap-dump/jvm.hprof

这一步执行时间会较长,会在heap dump当前目录下生成一些索引和其他文件,以提高分析的速度。在完成这步之后,我们再执行以下命令,来生成”Leak suspects”报告:

1
./ParseHeapDump.sh ../heap-dump/jvm.hprof org.eclipse.mat.api:suspects

这步执行完会生成一个压缩文件jvm_Leak_Suspects.zip,里面是HTML文件,通过这些文件即可像MAT Eclipse UI一样浏览分析报告了。

还可以执行以下选项来看其他一些报告:

1
2
3
org.eclipse.mat.api:suspects
org.eclipse.mat.api:overview
org.eclipse.mat.api:top_components

那如何获取java heap dump呢?

  1. jmap
    1
    jmap -dump:[live],format=b,file=<file-path> <pid>
    几个选项参数解释如下:
  • live: if set it only prints objects which have active references and discards the ones that are ready to be garbage collected. This parameter is optional
  • format=b: specifies that the dump file will be in binary format. If not set the result is the same
  • file: the file where the dump will be written to
  • pid: id of the Java process
  1. jcmd

    1
    jcmd <pid> GC.heap_dump <file-path>
  2. 启动参数配置

    1
    java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=<file-or-dir-path>

    当程序出现java.lang.OutOfMemoryError异常时才会dump heap,同时会出现如下日志:

    1
    2
    3
    4
    5
    java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    Dumping heap to java_pid12587.hprof ...
    Exception in thread "main" Heap dump file created [4744371 bytes in 0.029 secs]
    java.lang.OutOfMemoryError: Requested array size exceeds VM limit
    at com.baeldung.heapdump.App.main(App.java:7)

    产品环境推荐加上这个配置,对资源没有额外的损耗。

  3. jmx和jconsole
    如果需要实时查看,开启jmx通过jconsole查看即可。

参考