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分析报告
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
可以列出内存中的对象,对象的个数以及大小
histogram

  • Class Name:类名称,java类名
  • Objects:类的对象的数量,这个对象被创建了多少个
  • Shallow Heap:对象自身占用的内存大小,不包括它引用的对象
  • Retained Heap:当前对象大小+当前对象可直接或间接引用到的对象的大小总和

下面详细讲下Shallow Heap和Retained Heap:
Shallow Size:对象自身占用的内存大小,不包括它引用的对象。针对非数组类型的对象,它的大小就是对象与它所有的成员变量大小的总和。针对数组类型的对象,它的大小是数组元素对象的大小总和。
Retained Size:当前对象大小加上当前对象可直接或间接引用到的对象的大小总和。Retained Size就是当前对象被GC后,从Heap上总共能释放掉的内存。 释放的时候还要排除被GC Roots直接或间接引用的对象,他们暂时不会被被当做Garbage。

Retained
A对象的Retained Size=A对象的Shallow Size
B对象的Retained Size=B对象的Shallow Size + C对象的Shallow Size

2、Dominator Tree
可以列出那个线程,以及线程下面的那些对象占用的空间
Dominator Tree

  • percentage:列出所有对象在整个内存对象中所占百分比

3、Top consumers
根据类名和包名列出占用最大的对象
Top consumers

4、Duplicate Classes
查找出在不同classloader中加载的相同类

5、Leak Suspects
查看内存泄露情况
leak

Reports

在Reports标签中,有个重要的功能:

  • Leak Suspects:通过MAT自动分析泄漏的原因

总结

1.首先看retained size最大的那些数据,一般看内存都是想解决内存泄漏问题,可以通过Top Consumers或者是donimator tree等actions。
2.找到最大的数据后,通过list objects –> with outgoing references 查看具体持有了哪些对象,或者通过java basics –> classloader。查看这个是因为我们这次因为perm区满了,需要查看这个数据。到底还是哪些classloader加载了数据。

参考资料