tonglin0325的个人主页

使用jmap排查java程序内存泄露

1.使用jmap命令生成内存快照文件(Heap Profile)#

1
2
jmap -dump:format=b,file=heap.hprof ${pid}

如果生成快照的时候遇到如下报错

1
2
3
4
5
6
7
8
9
Dumping heap to /mnt/tmp/heap.hprof ...
Exception in thread "main" java.io.IOException: Premature EOF
at sun.tools.attach.HotSpotVirtualMachine.readInt(HotSpotVirtualMachine.java:292)
at sun.tools.attach.LinuxVirtualMachine.execute(LinuxVirtualMachine.java:200)
at sun.tools.attach.HotSpotVirtualMachine.executeCommand(HotSpotVirtualMachine.java:261)
at sun.tools.attach.HotSpotVirtualMachine.dumpHeap(HotSpotVirtualMachine.java:224)
at sun.tools.jmap.JMap.dump(JMap.java:247)
at sun.tools.jmap.JMap.main(JMap.java:142)

添加如下参数就可以解决

1
jmap -J-d64 -dump:format=b,file=/mnt/tmp/heap.hprof ${pid}

参考:jmap -dump导出jvm堆内存信息时报错

2.使用Eclipse Memory Analyzer工具对hprof文件进行分析#

如果机器的java版本是java8的话,需要注意MAT
 1.12.0版本需要jdk11,所以下载1.10.0版本

1
2
http://www.eclipse.org/downloads/download.php?file=/mat/1.10.0/rcp/MemoryAnalyzer-1.10.0.20200225-linux.gtk.x86_64.zip

否则会出现如下报错

1
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. Unable to init server: Could not connect: Connection refused  

由于堆栈快照文件可能会很大,所以需要修改 MemoryAnalyzer.ini 文件中的-Xmx1024m,比如改成-Xmx10240m,否则可能会遇到下面报错

1
an internal error occurred during parsing heap dump from

3.分析堆栈文件#

将快照文件从服务器上下载到本地,用MAT软件来分析hprof文件

查看内存泄露报告

 

发现有2处可疑的泄露

点击details,排查到可能是 class io.lettuce.core.AbstractRedisClient @ 0x41bc37380 引起的

 

排查使用的redis依赖是否有内存泄露的可能,找到

springboot使用redis压力测试出现内存泄漏解决方案

 

如果堆栈快照文件很大,不方便从服务器上下载到本地的话,可以直接在服务器上进行分析,再将分析的结果下载下来进行查看,分析的结果会以zip包形式生成,生成路径和hprof文件相同,如下

将zip文件下载下来,解压查看网页,就可以看到堆栈的分析报告,如下