在java进程发生内存溢出时导出堆内存快照有如下几种方式:
1.jvm环境变量设置内存溢出自动导出
jvm参数:-Xmx32M -Xms32M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./
社区版本idea执行可能无法导出内存映射,不使用idea即可。
提示:真实生产环境中,此种方式可能因为内存快照太大无法导出
2.jmap命令导出
2.1 使用jmap 帮助命令,查看一下帮助:
2.2 使用命令导出:
3.额外说明
jmap可以查看堆内存的一些详细信息:如下所示
4.单独MAT分析内存dump文件
4,1 首先安装:
安装地址:Eclipse Memory Analyzer Open Source Project | The Eclipse Foundation
根据自己情况,是否捐赠。如果不想捐赠,在下载页面选择阿里的镜像,即可(最新版本不支持jdk8):
支持jdk8的版本:
4.2 启动MAT:
点击如下exe文件:
需要注意的是,如果dump文件太大,需要调整它的内存才可以完成大dump文件的加载,这个配置文件需要exe启动后会自动生成:
4.3 MAT分析dump文件
这里给个程序实例:无限循环添加user。
查看概览,看到对象所占比例及排序:显然有个对象不正常,占了19m(我设置最大堆32m)
点击查看MAT详细分析结果:MAT猜想导致堆栈溢出原因
根据上图可以看到两个猜想的原因:
1.一个对象concurrenthashmap占据了65%的堆空间;
2.class文件加载过多,占据了14%。
毫无疑问是前者这个对象占据太多的原因,怎么分析尼?
点击如下图的柱状图(红色矩形框)查看对象实例数量排序,在正则表达式可以输入自己的包名过滤一下:
这里类对象16w个,显然不正常,我们可以查下谁引用的:
以下截图矩形的指定的按钮是查看类对象数量的:
可以看到占据最多空间的对象为第一个,点看如下:
结合概览、猜想及这两个查看类数量、类空间占据大小基本可以定位问题。