目录
前言
项目运行过程中,我们可能会遇到Java内存溢出Out Of Memory。此时我们可以借助内存分析工具MAT(Memory Analyzer Tool),来定位是哪里出现了问题。
一、MAT(Memory Analyzer Tool)
下载地址:Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation
注意:JDK-8建议使用11版本,否则会提示版本不兼容
二、软件初识
解压后目录内有个MemoryAnalyzer.ini文件,该文件里面有个-Xmx参数。该参数表示最大内存占用量,默认为1024m。
建议修改为小于本机内存大小,大于要分析的dump文件大小
-startup
plugins/org.eclipse.equinox.launcher_1.5.0.v20180512-1130.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_64_1.1.700.v20180518-1200
-vmargs
### -Xmx1024my原本默认为1024m,此处我修改为4096m
-Xmx4096m
三、捕获dump文件
首先在程序中模拟出一段内存溢出的逻辑:
@RequestMapping("/testOutOfMemory")
@ResponseBody
public void testOutOfMemory() throws Exception {
String name = "Aikes";
for (int i = 0; i < 10000000; i++) {
name += name;
}
System.out.println(name);
}
然后启动项目,开始准备捕获dump文件。这里的捕获方式分为两种,一种是主动捕获,一种是被动捕获:
1、主动方式
顾名思义,当内存溢出发生后,通过指令的方式手机当前应用程序下的内存使用情况。
1、通过(Linux) ps -ef|grep find 或者 (Dos)netstat -ano|findstr 查找java程序运行的PID
2、使用指令收集dump:jmap -dump:format=b,file=路径/heapdump.hprof 查到的PID
注意:主动获取dump文件必须是一出现内存异常就获取dump文件,这样获取的文件信息才比较准确。如果无法及时获取,推荐通过第二种方式获取dump文件。
2、被动方式
该方式是启动Java服务时,增加额外参数。当程序发生内存溢出时自动收集dump文件:
1、-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/opt/oom/heapdump.hprof
配置好后,调用我们预先模拟的内存溢出接口
稍等片刻控制台开始打印日志,提示出现内存溢出并且已经收集到dump文件到指定目录:
四、分析dump文件
打开下载好的mat软件,通过file-open打开抓取到的dump文件(hprof文件)
点击切换视图,可以看到内存占用百分之八十是因为这个线程,继续点开发现是一个超大的字符串"AikesAikesAikes...."
此时我们已经发现了内存溢出的直接原因,接下来要寻找出现这个问题的代码在哪里。再返回到最初的大饼图,点击最下面的details。然后点击See stacktrace 堆叠追踪。
这里可以看到完整的堆栈信息,里面可以发现我们增加模拟溢出代码的那个Java文件,并且爆发内存溢出的代码行也可以对上,至此溢出分析结束。
总结
模拟的内存溢出针对性很强,并且我们抓取dump文件也很及时,所以在分析的时候很简单。实际使用过程中面对的陷阱很多,需要从诸多可能中排查幕后凶手。Mat工具功能还很多,目前只是粗略的使用,后续如果有新的发现会继续补充到博文中。