模拟内存溢出&通过MAT分析
构建一个简单的Springboot应用,模拟出OOM场景,再导出heap dump文件,通过Mat分析。
搭建简易Springboot,模拟OOM场景
搭建一个简易的springboot工程,在controller层循环添加对象,直至OOM。
//循环添加对象,模拟OOM
List<UserVo> userVoListNew = new ArrayList<>();
for (int i = 0; i < 1024 * 1024 * 1024; i++) {
userVoListNew.addAll(userVoList);
}
具体代码地址,只要本地启动mysql、redis就跑起来了(一般半支烟直接docker启动,方便快捷):https://gitee.com/yclxiao/blog-dbpool/blob/oom/blog-dbpool-main/src/main/java/com/ycl/blog/controller/UserController.java
设置idea & 导出dump文件
1、配置idea的 VM options
在VM options中设置最大内存,以及设置dump文件位置
-Xmx512m
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/Users/yclxiao/Desktop/java_error_in_idea.hprof
2、启动项目
启动项目,swagger调用userController方法,等待OOM出现。最后会在配置的位置上出现java_error_in_idea.hprof
文件。
Mat分析dump文件
安装Memory Analyzer
下载地址:https://www.eclipse.org/mat/downloads.php,选择对应的平台安装即可,不需要安装eclipse。
导入dump文件
导入dump文件时,可能碰到以下错误:
An internal error occurred during: "Parsing heap dump from '/Users/yclxiao/Desktop/heapdump-1586847376115.hprof'".
Java heap space
解决方式:修改Applications/mat.app/Contents/Eclipse/MemoryAnalyzer.ini
中的最大内存配置
注意:半支烟是mac平台,window平台的文件位置稍微区别,小伙伴们自行查找下,哈哈!
分析dump文件
1、Mat分析概况
导出的dump文件大概400多M,通过MAT分析后,会看到一个饼状图,显示了排名靠前的大对象
2、点击Dominator Tree
& Leak Suspects
点击Dominator Tree
可以列出最大对象的排名,以及他们持有了哪些对象。点击Leak Suspects
可以看到比较有嫌疑的泄露以及系统概述。
3、点击Dominator Tree
可看到最大的Object[],左边显示了他持有的对象,根据这个UserVo我们大概能排查到具体的代码位置。
4、点击Leak Suspects
能大概看到是哪个线程的请求、看到是哪个大对象、看到是哪个具体业务代码,也有堆栈信息,一般根据这些信息能很快定位到有问题的业务代码。
总结
本文介绍了常见的分析OOM的方法。如果碰到线上问题先稳住不要慌,,第一时间保留线程(设置好OOM的dump位置),然后重启服务,再用Mat工具分析问题。
当然啦,问题也可能出现在别的地方,半支烟碰到问题一般是top、df、free这3个命令跑一遍,先看下机器的CPU、硬盘、内存等情况,再做后续分析。
如果更多好建议,欢迎与我交流。