专栏名称: 程序员大咖
为程序员提供最优质的博文、最精彩的讨论、最实用的开发资源;提供最新最全的编程学习资料:PHP、Objective-C、Java、Swift、C/C++函数库、.NET Framework类库、J2SE API等等。并不定期奉送各种福利。
目录
相关文章推荐
程序员的那些事  ·  B站知名up主何同学被指盗用开源项目,网友: ... ·  昨天  
码农翻身  ·  国产数据库,开始核心平替了! ·  2 天前  
程序猿  ·  .NET 9 正式发布! ·  3 天前  
码农翻身  ·  团队准备解散了。 ·  6 天前  
51好读  ›  专栏  ›  程序员大咖

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

程序员大咖  · 公众号  · 程序员  · 2017-09-30 10:24

正文

点击上方“程序员大咖”,选择“置顶公众号”

关键时刻,第一时间送达!


今天主要讲解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开发者门户

  • 程序员大咖整理发布,转载请联系作者获得授权

【点击成为安卓大神】