为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
Android

  测试mm在多次进入一个页面的时候突然app闪退,找到我说看这个页面有问题解决一下吧,只听我淡定的回复说之前这个页面没有问题怎么突然就有问题了呢,你再复现一下我看看(ps:其实我已经大概猜到是有可能是内存的问题,还让复现这样做是不是不太好啊5b912015000131ad00200020.jpg5b912015000131ad00200020.jpg),测试mm接着又测试了一段时间,果然又出现了同样的问题又来找我(ps:我的目的不是这个),这下子咱不能再让mm复现去了,恩,我知道了有可能是内存的问题,我现在就去改,改好了找你去(ps:出现问题了也得保持咱程序猿的风度)。马上打开MAT工具进行分析应用的内存使用情况,恩,分分钟解决,哈哈,速度就是这样快(ps:其实还是预防内存问题最重要啊)

   下面要进入正题了,同志们搬好小板凳细细的听过道来,如有疑问欢迎拍砖(ps:请不要拍脸)

   今天主要讲解MAT工具的作用同时通过一个简单的实例带同志们撸一把MAT,让你遇到内存问题能够分分钟解决(ps:好像有点夸张了5b912015000131ad00200020.jpg


1. 知识点

MAT(Memory Analyzer Tool), 是著名的Android内存分析工具,可以观察应用在运行过程中的内存情况,分析比较隐蔽的内存泄露问题。使用MAT之前有2个概念是要掌握的:Shallowheap和Retained heap。Shallow heap表示对象本身所占内存大小。Retained heap表示通过回收这一个对象总共能回收的内存。


2. 分析方法

   内存泄露的根本问题就是该回收的对象由于各种原因,没有被回收掉,而这些没有被回收的对象会存在内存的列表中,所以我们使用MAT工具的目的就是找到当前内存中对象的分布情况,查找那些异常对象,我常用的方法有以下两种

  (1) Histogram

      将当前内存中每个类的实例数量,如果某一个类的实例数量大于1那么这个类就有可能有问题

  (2) Dominator Tree

      列出当前内存中每个对象内存使用情况,通过观察对象的Retained heap是否过大,如果过大则有可能会有内存问题

    使用MAT打开Hprof文件以后在Overview里面会显示这两个动作

   5b9120150001369d06180284.jpg

3. 实战练习

    问题代码:

?


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;        }    } }</drawable>

  有经验的同志们可能已经发现上面代码存在严重的内存问题,哈哈,具体什么内存问题呢,老同志们先别说5b9120150001d64e00200020.jpg,容我使用MAT工具来分析一把。

  (1)使用AS下载HPROF文件,并转换为标准的HPROF的文件(ps:MAT只能打开标准的HPROF文件)

           5b9120150001af3618390194.jpg

5b9120160001424505170545.jpg

      (2)采用Histogram进行分析内存问题

    点击Histogram,进行搜索我们认为可能会出现问题的类名,可以进行模糊搜索,这里我们的问题类是TestMemoryActivity是 

         5b9120160001674606400129.jpg

         上面我们可以看到这个Activity对象竟然存在两个实例,这明显存在问题,接下来我们就要查找这两个实例具体的对象了

       5b91201600017a7e08550156.jpg

       5b9120170001f33510190116.jpg

         到这里我们已经查找到了当前类的具体对象,那么接下来我们就要分析这两个对象为什么会都存在,到底是谁在引用这他们导致这其中1个对象没有被没GC掉,同时同志们都知道如果弱引用的话GC发现内存不够的话会自动的进行清空的,所以弱应用不会照成内存的泄露问题,所以我们将弱引用对象进行排除

      5b91202b000179a910870228.jpg

5b91202b00012e4915840193.jpg

    上面的操作步骤已经将Activity的其中一个对象的引用清空进行展示出来,我们可以发现TestMemoryActivty这个类被内部类Person引用了(ps:内部类默认的引用外部类),也就是被personInstance引用了,到这里我们已经找到引用的问题所在,就是因为personInstance的引用导致Activty类不能释放内存,原因就是静态变量在app运行过程中都是存在内存的,如果引用了activity就会导致其不能释放

   好了,上面就是使用Histogram进行查找内存问题的全过程,下面我们开始使用Dominator Tree分析另一个问题\

    (3) Dominator Tree分析内存

       我们要通过DT查看对象的内存大小,发现较大的内存对象,进行分析改对象的问题

      5b91202b000174ce08500173.jpg

    在使用DT进行分析内存问问题的时候我们要重点的观察Retained Heap的大小,上图我们发现List的对象可是相当的大啊,那么接下来我们看一下到底是谁在引用呢

    5b91202c0001853308410165.jpg

   好了,到这里我们发现了这个list对象是testDrawables,那么我们在看看代码为什么这哥们这个大呢,因为我在循环中不断放入了drawable对象,不大就怪了,哈哈,在具体的使用过程中我们就是要发现异常的对象,然后去观察这个对象的大小是否合理然后进行下一步的判断

总结:

     在具体的代码中内存的问题必然要比我这里demo要复杂的多,所以需要同志们更加细心的去观察分析内存问题

    好了,写了半天也不知道同志们能看懂不,欢迎提问

原文链接:http://www.apkbus.com/blog-568772-72727.html

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消