点击上方“程序员大咖”,选择“置顶公众号”
关键时刻,第一时间送达!
今天主要讲解MAT工具的作用同时通过一个简单的实例带同志们撸一把MAT,让你遇到内存问题能够分分钟解决。(ps:好像有点夸张了)
知识点
MAT(Memory Analyzer Tool), 是著名的Android内存分析工具,可以观察应用在运行过程中的内存情况,分析比较隐蔽的内存泄露问题。使用MAT之前有2个概念是要掌握的:Shallowheap和Retained heap。Shallow heap表示对象本身所占内存大小。Retained heap表示通过回收这一个对象总共能回收的内存。
分析方法
内存泄露的根本问题就是该回收的对象由于各种原因,没有被回收掉,而这些没有被回收的对象会存在内存的列表中,所以我们使用MAT工具的目的就是找到当前内存中对象的分布情况,查找那些异常对象,我常用的方法有以下两种:
(1) Histogram
将当前内存中每个类的实例数量,如果某一个类的实例数量大于1那么这个类就有可能有问题。
(2) Dominator Tree
列出当前内存中每个对象内存使用情况,通过观察对象的Retained heap是否过大,如果过大则有可能会有内存问题。
使用MAT打开Hprof文件以后在Overview里面会显示这两个动作。
实战练习
问题代码:
public class TestMemoryActivity extends AppCompatActivity implements View.OnClickListener { public static Person personInstance;
private Drawable testDrawable;
List testDrawables; ImageView iv_show; @Override
protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_test_wifi); if(personInstance == null){ personInstance = new Person("内存溢出"); } iv_show = (ImageView) findViewById(R.id.iv_show); testDrawable = getDrawable(R.mipmap.intelligent_bg_trans);
if(testDrawables==null){ testDrawables = new ArrayList<>(); } iv_show.setOnClickListener(this); } @Override
public void onClick(View v) {
while(true){ testDrawables.add(testDrawable); } } private class Person{ String name; Person(String name) { this.name = name; } }}
有经验的同志们可能已经发现上面代码存在严重的内存问题,哈哈,具体什么内存问题呢,老同志们先别说,容我使用MAT工具来分析一把。
1、使用AS下载HPROF文件,并转换为标准的HPROF的文件(ps:MAT只能打开标准的HPROF文件)
2、采用Histogram进行分析内存问题
点击Histogram,进行搜索我们认为可能会出现问题的类名,可以进行模糊搜索,这里我们的问题类是TestMemoryActivity是
上面我们可以看到这个Activity对象竟然存在两个实例,这明显存在问题,接下来我们就要查找这两个实例具体的对象了。
到这里我们已经查找到了当前类的具体对象,那么接下来我们就要分析这两个对象为什么会都存在,到底是谁在引用这他们导致这其中1个对象没有被没GC掉,同时同志们都知道如果弱引用的话GC发现内存不够的话会自动的进行清空的,所以弱应用不会照成内存的泄露问题,所以我们将弱引用对象进行排除。
上面的操作步骤已经将Activity的其中一个对象的引用清空进行展示出来,我们可以发现TestMemoryActivty这个类被内部类Person引用了(ps:内部类默认的引用外部类),也就是被personInstance引用了,到这里我们已经找到引用的问题所在,就是因为personInstance的引用导致Activty类不能释放内存,原因就是静态变量在app运行过程中都是存在内存的,如果引用了activity就会导致其不能释放。
好了,上面就是使用Histogram进行查找内存问题的全过程,下面我们开始使用Dominator Tree分析另一个问题。
3、Dominator Tree分析内存
我们要通过DT查看对象的内存大小,发现较大的内存对象,进行分析改对象的问题。
在使用DT进行分析内存问问题的时候我们要重点的观察Retained Heap的大小,上图我们
发现List的对象可是相当的大啊,那么接下来我们看一下到底是谁在引用呢。
到这里我们发现了这个list对象是testDrawables,那么我们在看看代码为什么这哥们这个大呢,因为我在循环中不断放入了drawable对象,不大就怪了,哈哈,在具体的使用过程中我们就是要发现异常的对象,然后去观察这个对象的大小是否合理然后进行下一步的判断。
总结
在具体的代码中内存的问题必然要比我这里demo要复杂的多,所以需要同志们更加细心的去观察分析内存问题。
来自: 安卓巴士Android开发者门户
程序员大咖整理发布,转载请联系作者获得授权
【点击成为安卓大神】