MAT-Memory Analyzer Tool

2019-08-06  本文已影响0人  东方灵龙

简介

MAT(Memory Analyzer Tool),一个基于Eclipse的内存分析工具,是一个快速、功能丰富的JAVA heap分析工具,它可以帮助我们查找内存泄漏和减少内存消耗。使用内存分析工具从众多的对象中进行分析,快速的计算出在内存中对象的占用大小,看看是谁阻止了垃圾收集器的回收工作,并可以通过报表直观的查看到可能造成这种结果的对象。

除了Eclipse插件版,MAT也有独立的不依赖Eclipse的版本,只不过这个版本在调试Android内存的时候,需要将DDMS生成的文件进行转换,才可以在独立版本的MAT上打开。因为DDMS生成的是Android格式的HPROF(堆转储)文件,而MAT只能识别JAVA格式的HPROF文件。不过Android SDK中已经提供了这个Tools,所以使用起来也是很方便的。

要调试内存,首先需要获取HPROF文件,HPROF文件存储的是特定时间点,java进程的内存快照。有不同的格式来存储这些数据,总的来说包含了快照被触发时java对象和类在heap中的情况。由于快照只是一瞬间的事情,所以heap dump中无法包含一个对象在何时、何地(哪个方法中)被分配这样的信息。

官网跳转

MAT涉及的词汇介绍

要看懂MAT的列表信息,Shallow heap、Retained Heap、GC Root这几个概念一定要弄懂。

Shallow heap

Shallow size就是对象本身占用内存的大小,不包含其引用的对象。

因为不像c++的对象本身可以存放大量内存,java的对象成员都是些引用
。真正的内存都在堆上,看起来是一堆原生的byte[], char[], int[],所以我们如果只看对象本身的内存,那么数量都很小。所以我们看到柱状图是以Shallow size进行排序的,排在第一位第二位的一般是byte,char 。

Retained Set

持有对象集合:
Retained Set是指当一个对象被GC时,会因为对象的释放而同时被GC掉的所有对象的集合;或者说是对象本身和对象所引用对象的集合;

Retained Heap

Retained Heap则表示一个对象的Retained Set中所有对象的Shallow Size的总和。换句话说,Retained Heap就表示如果一个对象被释放掉,那会因此而被释放的总的heap大小。于是,如果一个对象的某个成员new了一大块int数组,那这个int数组也可以计算到这个对象中。相对于shallow heap,Retained heap可以更精确的反映一个对象实际占用的大小(因为如果该对象释放,retained heap都可以被释放)。

这里要说一下的是,Retained Heap并不总是那么有效。例如我在A里new了一块内存,赋值给A的一个成员变量。此时我让B也指向这块内存。此时,因为A和B都引用到这块内存,所以A释放时,该内存不会被释放。所以这块内存不会被计算到A或者B的Retained Heap中。为了纠正这点,MAT中的Leading Object(例如A或者B)不一定只是一个对象,也可以是多个对象(Leading Set)。此时,(A, B)这个组合的Retained Set就包含那块大内存了。

1670d42206688f2e.jpg

很显然,从上面的对象引用图计算Retained Memory并不那么直观高效。比如A和B的Retained Memory只有它们自身,而E的Retained Memory则是E和G,G的Retained Memory也只是它自身。为了更直观的计算Retained Memory,MAT引入了Dominator(统治者) Tree的概念。

Dominator(统治者) Tree

1670d42244a61099.jpg

在Dominator Tree中,有下面一些非正式的定义:

Dominator Tree还有以下重要属性:

对应到MAT UI上,在dominator tree这个view中,显示了每个对象的shallow heap和retained heap。而点击右键,可以List objects中选择with outgoing references和with incoming references。这是个真正的引用图的概念,

GC ROOTS

首先要说一下GC的原则:

垃圾回收器会尝试回收所有非GC roots的对象。所以如果你创建一个对象,并且移除了这个对象的所有指向,它就会被回收掉。但是如果你将一个对象设置成GC roots,那它就不会被回收掉。

那么GC又如何判断某个对象是否可以被回收呢?

安卓的垃圾回收是通过可达性分析来搞定的,也就是说,从GC Roots 到这个对象不可达时,垃圾回收器就会释放掉它。

一个GC root就是一个对象,这个对象从堆外可以访问读取。以下一些方法可以使一个对象成为GC root:

Java的引用级别

从最强到最弱,不同的引用(可到达性)级别反映了对象的生命周期。

上一篇 下一篇

猜你喜欢

热点阅读