今天我们来一起学习一下如何利用MAT(Memory Analyzer Tool)快速的定位Java程序的内存泄漏问题。
先来科普一下MAT:
The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.Use the Memory Analyzer to analyze productive heap dumps with hundreds of millions of objects, quickly calculate the retained sizes of objects, see who is preventing the Garbage Collector from collecting objects, run a report to automatically extract leak suspects.
意思就是:
Eclipse Memory Analyzer是一个快速的并且功能丰富的Java堆分析工具,旨在帮助你发现内存泄漏问题和减少内存消耗。
使用MAT来分析生产数以亿计的对象堆转储文件,快速计算存活对象的大小,发现谁在阻碍GC回收对象,形成一个报告来自动提取内存泄漏嫌疑对象。
安装独立版本的MAT
官网下载Memory Analyzer 1.9.0 Release,jdk1.8就下载这个,下载地址:
https://eclipse.dev/mat/previousReleases.php
下载zip包解压后,即可双击运行应用程序,MAT欢迎页面:
本地Windows获取Heap Dump文件
写一个简单的类并运行来获取Heap Dump文件:
public static void main(String[] args) {
HashMap<String, Object> resultMap = new HashMap<>(100000);
for (int i=0; i<100000; i++) {
String[] strings = new String[10000];
resultMap.put(String.valueOf(i), strings);
}
}
配置启动参数
具体值为
-Xms128m -Xmx256m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:\zhushanglin\test
运行main方法会报错如下:
Java Heap Dump文件已到手,在配置的 -XX:HeapDumpPath=C:\zhushanglin\test目录下,开始分析!
MAT分析Java Heap Dump文件
MAT打开本地dump文件,选择Leak Suspects Report:
大家看到上面的图是不是基本上就可以看见问题点了?已经明确的告诉你问题嫌疑点:(a)234.6M,把配置的启动参数中分配的内存235.8M吃没了。
点击黄色区域"See stacktrace"查看堆栈信息:
立刻便能定位程序中内存泄漏的问题代码了。
以上只是实验阶段,那么在生产环境中当我们怀疑线上业务有内存泄漏问题时候怎么办呢?还是需要拿到Java Heap Dump文件,但是这个时候注意了,一定要保留现场的情况下去拿dump文件,否则重启了或者等Full GC了,现场就没有了。
接下来我们介绍在Linux中,如何通过Jmap来获取Java Heap Dump文件。
jmap -h查看linux下jmap命令的用法,大家可以看看他的Usage和options介绍以及如何使用,这里就不对每个参数进行详细介绍了。先查看当前运行的java程序的进程Id:
ps -fC java 拿到进程id
然后获取转储文件:
jmap -dump:live,format=b,file=dump.phrof 2188001
大家在使用上述命令时候一定要小心,如果服务器上的JVM heap过大,会造成应用“Stop the World”,建议使用参数的形式,在启动应用程序的时候就把参数带上,这样也会在内存溢出的时候,能够及时的保存线程dump文件。
把服务器上的dump.phrof文件下载到本地用MAT打开,开启你的分析之路吧~