Memory Analyzer分析堆快照文件过程
简介
当应用发生OutOfMemoryError时,我们需要通过jmap -dump:live,format=b,file=/home/dump20190318.hprof <pid>
导出当前堆快照文件,并利用Memory Analyzer工具进行分析。
造成OutOfMemoryError原因一般有2种:
- 内存泄露,对象已经死了,无法通过垃圾收集器进行自动回收,通过找出泄露的代码位置和原因,才好确定解决方案;
- 内存溢出,内存中的对象都还必须存活着,这说明Java堆分配空间不足,检查堆设置大小(-Xmx与-Xms),检查代码是否存在对象生命周期太长、持有状态时间过长的情况。
过程
1、打开堆文件,file–>open dump heap–>leak suspects report–>finish
2、OverView分析报告
biggest object by retained size
biggest object by retained size:显示在内存较大的对象信息。单击某个扇区就可以根据该对象对其引用情况等进行分析
- list objects–>with outgoing references : 查看这个对象持有的外部对象引用
-->with incoming references : 查看这个对象被哪些外部对象引用
- show objects by class–>with outgoing references :查看这个对象类型持有的外部对象引用
-->with incoming references :查看这个对象类型被哪些外部对象引用
- path to gc roots : 显示不同类型引用(strong reference、soft reference 、weak reference)到跟节点的路径
- merge shorest paths to gc roots : 合并最短路径到root节点,这个具体没试过
- java basics:
–>class loader explorer:该对象对应的classloader信息
–>thread details:线程信息
–>thread overview and stacks:线程堆栈
–>group by value:根据某个字段统计出现的个数- leak Identification–>top consumers :几个大消耗内存的对象
Action
在Action标签中,有以下几个重要的功能:
1、Histogram
可以列出内存中的对象,对象的个数以及大小
- Class Name:类名称,java类名
- Objects:类的对象的数量,这个对象被创建了多少个
- Shallow Heap:对象自身占用的内存大小,不包括它引用的对象
- Retained Heap:当前对象大小+当前对象可直接或间接引用到的对象的大小总和
下面详细讲下Shallow Heap和Retained Heap:
Shallow Size:对象自身占用的内存大小,不包括它引用的对象。针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。针对数组类型的对象,它的大小是数组元素对象的大小总和。
Retained Size:当前对象大小加上当前对象可直接或间接引用到的对象的大小总和。Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。 释放的时候还要排除被GC Roots直接或间接引用的对象,他们暂时不会被被当做Garbage。
A对象的Retained Size=A对象的Shallow Size
B对象的Retained Size=B对象的Shallow Size + C对象的Shallow Size
2、Dominator Tree
可以列出那个线程,以及线程下面的那些对象占用的空间
- percentage:列出所有对象在整个内存对象中所占百分比
3、Top consumers
根据类名和包名列出占用最大的对象
4、Duplicate Classes
查找出在不同classloader中加载的相同类
5、Leak Suspects
查看内存泄露情况
Reports
在Reports标签中,有个重要的功能:
- Leak Suspects:通过MAT自动分析泄漏的原因
总结
1.首先看retained size最大的那些数据,一般看内存都是想解决内存泄漏问题,可以通过Top Consumers或者是donimator tree等actions。
2.找到最大的数据后,通过list objects –> with outgoing references 查看具体持有了哪些对象,或者通过java basics –> classloader。查看这个是因为我们这次因为perm区满了,需要查看这个数据。到底还是哪些classloader加载了数据。