记一次MAT内存分析

1、背景

记录一次内存分析的简单实践,目的是找出占用内存较大的对象和无效的内存分配

2、工具

2.1、 DDMS或者Android Studio

DDMS:抓取内存快照

Android Studio的Profiler:抓取内存快照并分析(支持android 5.0以上)

2.2、 MAT(Memory Analyzer)

内存快照文件分析工具

3、步骤

3.1、 抓取内存快照

DDMS支持5.0以下的系统,以DDMS为例。

在这里插入图片描述
在这里插入图片描述

选择目标apk,并抓取内存快照,可以先GC几次确保内存快照准确。

生成hprof文件并转换。这时生成的文件不能直接使用,要经过转换。转换工具在Android SDK的platform-tools目录下,如:

xxx\Android\SDK\platform-tools\hprof-conv.exe -z xxx\xxx\src.hprof xxx\xxx\src-conv.hprof

生成的src-conv.hprof文件就可以在mat中打开了。

3.2 分析内存快照

3.2.1、总览

打开上一步得到的hprof文件
在这里插入图片描述

这里可以看到大致的内存占用信息,放到饼状图上,还能看到具体的占用对象,如:
在这里插入图片描述
在这里插入图片描述
这里看到占用最多的是bitmap,其次是glide。

3.2.2、Dominator Tree

直观地列出大对象

在这里插入图片描述

3.2.3、Histogram统计

Histogram可以统计出各个对象占用的具体大小,并可以排序、筛选等。比如这里按Retained Heap降序排

在这里插入图片描述

能看到具体是什么对象,占用了多少内存,对象有多少个等信息。

3.2.4 with outgoing/incoming references

列出引用对象

  • with outgoing references:我引用了谁
  • with incoming references:谁引用了我

这里bitmap占用最大,选中bitmap右键:

在这里插入图片描述

比如查看什么对象引用了bitmap(with incoming references):

在这里插入图片描述

可以看到有两个对象引用了bitmap,分别是IndexLoadingDialog里的mIvLoading和TextSeekBar里的mProgressDrawable。

3.2.5 Merge Shortest Paths to GC Roots

如果上面的方法还不够直接的话,可以使用Merge Shortest Paths to GC Roots

在这里插入图片描述

可以筛选引用类型:如去除弱引用、软引用等,这里选只保留强应用,即exclude all phantom/weak/soft etc. references

在这里插入图片描述

这里很直观的显示了引用对象。

3.2.6 利用表达式筛选

在Histogram统计界面,可以利用正则表达式筛选出想看的类,比如使用包名筛选:

在这里插入图片描述
针对性的去查找大内存对象。

3.3 优化大内存对象

通过上面的分析,已经大致知道了什么对象占用内存比较大和引用位置。就可以针对具体的对象进行优化了,比如这里图片压缩一下、TextSeekBar只用于下载更新apk时使用,可以用ViewStub标签延迟加载等。假设IndexLoadingDialog里的mIvLoading可以去掉,去掉之后重复上面的步骤:

在这里插入图片描述

可以看到内存已经从之前的4.2m降到了345k。

4、结语

mat还可以分析内存泄漏,比如打开/关闭activity多操作几次,查看内存快照中activity的对象个数,就可以判断是否存在泄漏了。虽然看了不少内存优化的文章、介绍,但是一直都没有什么实感,这次终于有了把理论用到了实践当中的感觉。

发布了19 篇原创文章 · 获赞 25 · 访问量 5585

猜你喜欢

转载自blog.csdn.net/pxq10422/article/details/105310369