logo
当前位置:首 页 > 移动开发 >android > 查看文章

Android进阶之少年来撸一把MAT工具

android, 移动开发 你是第3013个围观者 0条评论 供稿者: 标签:

今天主要讲解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<drawable> 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要复杂的多,所以需要同志们更加细心的去观察分析内存问题。

说说梦想,谈谈感悟 ,聊聊技术,有啥要说的来github留言吧 https://github.com/cjx2328

—— 陈 建鑫

陈建鑫
你可能也喜欢Related Posts
footer logo
未经许可请勿自行使用、转载、修改、复制、发行、出售、发表或以其它方式利用本网站之内容。站长联系:cjx2328#126.com(修改#为@)
Copyright ©ziao Studio All Rights Reserved. E-mail:cjx2328#126.com(#号改成@) 沪ICP备14052271号-3