🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
## 一、概述 堆Dump是反应Java堆使用情况的内存镜像,其中主要包括系统信息、虚拟机属性、完整的线程Dump、所有类和对象的状态等。 一般,在内存不足、GC异常等情况下,我们就会怀疑有内存泄露。这个时候我们就可以制作堆Dump来查看具体情况; ## 二、方案 使用jmap即可实现; ### **基础入门** 把当前堆内存的快照转储到hprof(也可以命名为其他扩展类型)文件中,然后使用MAT、VisualVM等分析工具导入,即可对内存快照进行分析; ``` jmap -dump:format=b,file=/usr/lib/app/out.hprof ${javaPID} ``` 生成的文件,通过MAT工具即可分析; 查看各对象使用情况: ![](https://img.kancloud.cn/b9/94/b994189d86dad571fe978db3d5d63554_1920x1039.png) 查看各类引用(强、软、弱、虚): ![](https://img.kancloud.cn/19/f9/19f9ce965fba67a8a691af2f0cd48cfd_1920x1039.png) >[danger] 可以间隔性做2份hprof对比,更容易查出问题; ### **多次对比分析** 分别打开两次间隔了一段时间dump的hprof文件; ![](https://img.kancloud.cn/9f/cd/9fcdcd5734f08b4fe1d05421d3cb6274_1920x1039.png) ### **生产环境OOM分析** 在生产环境中,OOM发生后,需自动dump,需要修改JVM参数,增加: ``` -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/lib/app/raydump.hprof ``` tomcat中,在catalina.sh中进行设置,首行增加配置即可; ``` CATALINA_OPTS="$CATALINA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/lib/app/raydump.hprof" ``` 启动后: ![](https://img.kancloud.cn/af/dd/afdde16769da81ca1e1b7333cf9e5a3d_1166x171.png) ## 三、分析指标 ### **术语** **Shallow Heap**表示对象本身占用内存的大小,不包含对其他对象的引用,也就是对象头加成员变量(不是成员变量的值)的总和; **Retained Heap**是该对象自己的Shallow Heap,并加上从该对象能直接或间接访问到对象的Shallow Heap之和。换句话说,Retained Heap是该对象GC之后所能回收到内存的总和; ### **Dominator Tree** Dominator Tree视图基于对象实例的角度; 通过Dominator Tree视图可以很容易的找出占用内存最多的几个对象; ![](https://img.kancloud.cn/5b/fb/5bfb48c999618b78b5493523bf4239e6_1920x1039.png) 能看到,内存占用比率比较高的对象: ![](https://img.kancloud.cn/a7/9a/a79a86293b260f8816fd0a7832b24c26_1920x1039.png) 选择查看的对象,并分析,一般就能发现问题了: ### **Histogram(直方图)** Histogram视图基于类的角度; 可以列出每个类产生的实例数量,以及所占用的内存大小和百分比; Shallow Heap 和 Retained Heap分别表示对象自身不包含引用的大小和对象自身并包含引用的大小,默认的大小单位是 Bytes,可以在 Window - Preferences 菜单中设置单位,图中设置的是KB; ![](https://img.kancloud.cn/2d/fe/2dfe955bddb1d139b7cf19a08c170e00_1920x1039.png) 如果存在内存溢出,时间久了溢出类的实例数量或者内存占比会越来越多,排名也越来越靠前。可以点击工具类上的图标进行对比,通过多次对比不同时间点下的直方图对比就很容易把溢出的类找出来; ### **示例** 普通分析: ![](https://img.kancloud.cn/de/46/de4688d559e36d8dcd83cabe6552ce23_1920x1039.png) 发现这个对象,占用比例不断攀升,经分析,这里产生了内存泄露,修复后运行; OOM发生的时候,快照分析: ![](https://img.kancloud.cn/14/81/14818032a2b6b9158d0b89cedfe66358_1920x1039.png) 看看线程里面,OOM发生的时候,找到相关线索; ![](https://img.kancloud.cn/b0/88/b088edefcee97d42e0910fb562f85555_1920x1039.png) ![](https://img.kancloud.cn/ae/ce/aeceb9394a540325569ef4a0683ac039_1920x1039.png) 这个时候,就很容易发现问题了,修复,再次验证,对比前后内存堆栈分析图,即可;