获取 JVM 的 dump 的两种方式。

通过配置 JVM 参数自动导出

在 JVM 启动参数加增加两个参数

1
2
3
4
#出现 OOME 时生成堆 dump: 
-XX:+HeapDumpOnOutOfMemoryError
#生成堆文件地址:
-XX:HeapDumpPath=/opt/jvmlogs/

-XX:HeapDumpPath 是指定 dump 输出的目录

手动通过 Jmap 命令导出

第二种是在程序可能发生异常时手动导出

1
jmap -dump:format=b,file=/var/logs/heap.hprof $PID
  1. format=b 表示输出二进制格式
  2. file 指定输出的文件目录
  3. PID 表示指定 JVM 进程的 PID

第一种方式是需要等待当前JVM出现问题后才能生成dmp文件,实时性不高,
第二种方式在执行时,JVM是暂停服务的,所以对线上的运行会产生影响,所以建议第一种方式。

dump 分析

dump 的具体分析可能使用工具进行,比如Jprofiler 或者 Eclipse 的 Memory Analyzer Tool 工具,包括 IDEA 中打开 dump 文件也能展示分析
Eclipse Memory Analyzer Tool 展示效果
image.png

IDEA 展示效果
image.png

超大dump分析

一般导出的dump文件都比较大,在本地分析可能受限于自身电脑性能与内存的原因无法完成。比如dump文件可能有5、6G,也可能有20、30G的大小。
这种情况下我们可以直接在Linux服务器上分析,需要使用Memory Analyzer Tools这个工具。
下载地址:https://www.eclipse.org/mat/downloads.php
历史版本下载地址:https://eclipse.dev/mat/previousReleases.php
下载的时候需要看下自己Linux的版本,下载匹配的版本即可。

1
2
[root@KSSHUAT01450 /data]# uname -m
x86_64

另外就是需要下载与自己JDK匹配的版本,否则启动报错:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@KSSHUAT01450 /data/mat]# ./ParseHeapDump.sh heap.hprof  org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components
Unrecognized option: --add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
MemoryAnalyzer:
JVM terminated. Exit code=1
/opt/jdk8//bin/java
--add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
-Xmx2048m
-jar /data/mat//plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar
-os linux
-ws gtk
-arch x86_64
-launcher /data/mat/MemoryAnalyzer
-name MemoryAnalyzer
--launcher.library /data/mat/plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.2.800.v20231003-1442/eclipse_11802.so
-startup /data/mat/plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar
--launcher.overrideVmargs
-exitdata 3
-consolelog
-application org.eclipse.mat.api.parse heap.hprof org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components
-vm /opt/jdk8//bin/java
-vmargs
--add-exports=java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED
-Xmx2048m
-jar /data/mat/plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar

如果是JDK8建议去历史版本中下载Memory Analyzer 1.10.0 Release版本,测试可以正常启动。
下载下来是一个Zip压缩包,直接上传到Linux服务器上进行解压。

1
[root@KSSHUAT01450 /data]# unzip MemoryAnalyzer-1.10.0.20200225-linux.gtk.x86_64.zip

解压完成会得到一个mat目录,在该目录下执行命令

1
[root@KSSHUAT01450 /data]# ./ParseHeapDump.sh heap.hprof  org.eclipse.mat.api:suspects org.eclipse.mat.api:overview org.eclipse.mat.api:top_components

命令中的heap.hprof 则是我们自己的dump文件,我是把它移动到了Mat目录当中。
如果内存不足可能会报错:java.lang.OutOfMemoryError: Java heap space
需要调整一下Mat工具的堆内存配置,编辑mat目录下的 MemoryAnalyzer.ini ,调整 -Xmx的参数即可

1
2
3
4
5
6
7
8
[root@KSSHUAT01450 /data]# vim MemoryAnalyzer.ini 
-startup
plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.gtk.linux.x86_64_1.1.700.v20180518-1200
-vmargs
-Xmx10240m
~