摘要:Eclipse Memory Analysis Tools (MAT) 是一个分析 Java堆数据的专业工具,用它可以定位内存泄漏的原因。
正文:
Memory Analyzer的安装
- Eclipse->Help->Eclipse Marketplace
- 安装完成后可以调用jdk工具jps查看当前的java进程,然后调用jmap将该进程的内存heap输出到文件。
- 通过MAT以图像形式直观的展示内存泄漏报表等
首先Eclipse->File->Open File 打开上一步生成的文件
第一个选项是内存泄漏报表(自动检查可能存在内存泄露的对象,通过报表展示存活的对象以及为什么他们没有被垃圾收集);
第二个是对象报表(对可疑对象进行分析,如字符串是否定义重了,空的collection、finalizer以及弱引用等);
这里我们打开第一个:
Memory Analyzer主界面介绍
- 下面的Histogram(列出内存中的对象,对象的个数以及大小)这里我们可以使用正则去进行匹配
可以在具体的Class右键List objects->with incoming…./outgoing…查看该Class的实例
1. outgoing references :表示该对象的出节点(被该对象引用的对象)。
2. incoming references :表示该对象的入节点(引用到该对象的对象)。
- 下面的Dominator Tree是列出最大的对象以及其依赖存活的Object (大小是以Retained Heap为标准排序的)
- 而Top Consumers则是通过图形列出最大的Object
- Duplicate Class是通过MAT自动分析泄漏的原因
一般Histogram和 Dominator Tree是最常用的。
Memory Analyzer中概念介绍
- Shallow heap
Shallow size就是对象本身占用内存的大小,不包含其引用的对象。
1. 常规对象(非数组)的Shallow size由其成员变量的数量和类型决定。
2. 数组的shallow size由数组元素的类型(对象类型、基本类型)和数组长度决定
- Retained Heap
它表示如果一个对象被释放,那么因为该对象的释放而减少引用从而导致释放所有的对象所占用的heap大小
为了计算Retained Memory,MAT引入了Dominator Tree。加入对象A引用B和C,B和C又都引用到D(一个菱形)。此时要计算Retained Memory,A的包括A本身和B,C,D。B和C因为共同引用D,所以他俩的Retained Memory都只是他们本身。D当然也只是自己。我觉得是为了加快计算的速度,MAT改变了对象引用图,而转换成一个对象引用树。在这里例子中,树根是A,而B,C,D是他的三个儿子。B,C,D不再有相互关系。把引用图变成引用树,计算Retained Heap就会非常方便,显示也非常方便。对应到MAT UI上,在dominator tree这个view中,显示了每个对象的shallow heap和retained heap。然后可以以该节点位树根,一步步的细化看看retained heap到底是用在什么地方了。要说一下的是,这种从图到树的转换确实方便了内存分析,但有时候会让人有些疑惑。本来对象B是对象A的一个成员,但因为B还被C引用,所以B在树中并不在A下面,而很可能是平级,如下图所示。
为了纠正这点,MAT中点击右键,可以List objects中选择with outgoing references和with incoming references。这是个真正的引用图的概念
- GC Root
GC发现通过任何reference chain(引用链)无法访问某个对象的时候,该对象即被回收。名词GC Roots正是分析这一过程的起点,例如JVM自己确保了对象的可到达性(那么JVM就是GC Roots),所以GC Roots就是这样在内存中保持对象可到达性的,一旦不可到达,即被回收。通常GC Roots是一个在current thread(当前线程)的call stack(调用栈)上的对象(例如方法参数和局部变量),或者是线程自身或者是system class loader(系统类加载器)加载的类以及native code(本地代码)保留的活动对象。所以GC Roots是分析对象为何还存活于内存中的利器。
在Histogram或者Domiantor Tree的某一个条目上,右键可以查看其GC Root Path
参考:
http://blog.csdn.net/yxz329130952/article/details/50288145
http://www.jianshu.com/p/d8e247b1e7b2