性能优化03_MAT

Android性能优化汇总

MAT工具全称为Memory Analyzer Tool,一款详细分析Java堆内存的工具,为了使用该工具,我们需要hprof文件。

MAT下载地址

一 MAT解析hprof文件

AndroidMonitor生成.hprof文件不能不能直接被MAT使用,需要进行一步转化,可以使用hprof-conv命令来转化

  1. sdk\platform-tools>hprof-conv 路径下打开命令行
  2. 执行命令:
    hprof-conv 源文件 输出文件
    例如:在这里插入图片描述
  3. 打开MAT后选择File->Open File选择我们刚才生成的doctorq.hprof文件
    在这里插入图片描述
  4. 选择该文件后,MAT会有几秒种的时间解析该文件,有的hprof文件可能过大,会有更长的时间解析,解析后,展现在我们的面前的界面如下:
    在这里插入图片描述
    这是个总览界面,会大体给出一些分析后初步的结论

二 MAT视图

Overview视图

该视图会首页总结出当前这个Heap dump占用了多大的内存,其中涉及的类有多少,对象有多少,类加载器,如果有没有回收的对象,会有一个连接,可以直接参看(图中的Unreachable Objects Histogram)。
比如该例子中显示了Heap dump占用了41M的内存,5400个类,96700个对象,6个类加载器。
然后还会有各种分类信息:
Biggest Objects by Retained Size
会列举出Retained Size值最大的几个值,你可以将鼠标放到饼图中的扇叶上,可以在右侧看出详细信息:

在这里插入图片描述
图中灰色区域,并不是我们需要关心的,他是除了大内存对象外的其他对象,我们需要关心的就是图中彩色区域,比如图中2.4M的对象,我们来看看该对象到底是啥:
在这里插入图片描述
该对象是一个Bitmap对象,你如果想知道该对象到底是什么图片,可以使用图片工具gimp工具浏览该对象.

histogram视图

histogram视图主要是查看某个类的实例个数,比如我们在检查内存泄漏时候,要判断是否频繁创建了对象,就可以来看对象的个数来看。也可以通过排序看出占用内存大的对象:

在这里插入图片描述
默认是类名形式展示,你也可以选择不同的显示方式,有以下四种方式:
在这里插入图片描述
演示一下:
在这里插入图片描述

Dominator tree视图

在这里插入图片描述

该视图会以占用总内存的百分比来列举所有实例对象,注意这个地方是对象而不是类了,这个视图是用来发现大内存对象的。这些对象都可以展开查看更详细的信息,可以看到该对象内部包含的对象:

在这里插入图片描述

Leaks suspects视图

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

这个视图会展示一些可能的内存泄漏的点,比如上图上图显示有3个内存泄漏可疑点,我们以Problem Suspect 1为例来理解该报告,首先我们来看该可疑点详细信息:

在这里插入图片描述
上面信息显示ImageCahe类的一个实例0xa50819f8占用了14.19%的内存,具体值为5147200字节(5147200/1024/1024=4.9M),并存放在LinkedHashMap这个集合中,然后我们点击Details跳转到更详细的页面:

在这里插入图片描述
这样我们就能找到在我们的app源码中造成该泄漏可疑点的地方,很容易去定位问题.

三 MAT定位泄漏

1 Demo

一个正常的自定义View:MyView

public class MyView extends View {
    public MyView(Context context) {
        super(context);
        init();
    }


    public MyView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        ListenerCollector collector = new ListenerCollector();
        collector.setListener(this,myListener);
    }

    public interface MyListener {
        void mylistenerCallback();
    }

    private MyListener myListener = new MyListener() {
        @Override
        public void mylistenerCallback() {
            System.out.print("被调用");
        }
    };
}

ListenerCollector

public class ListenerCollector {

    static private WeakHashMap<View, MyView.MyListener> slistener = new WeakHashMap<>();

    public void setListener(View view, MyView.MyListener listener) {
        slistener.put(view, listener);
    }

    public static void clearListeners() {
        //移除所有监听
        slistener.clear();
    }
}

ListenerActivity

public class ListenerActivity extends AppCompatActivity {


    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyView myView = new MyView(this);
        setContentView(myView);
    }

  /*  @Override
    protected void onStop() {
        super.onStop();
        ListenerCollector.clearListeners();
    }*/
}

2 横竖屏切换出现泄漏

运行进入这个Activity的页面,横屏后,分析内存,AndroidMonitor发现Activity泄漏(视图中ListenerActivity 有两个)

在这里插入图片描述

这样就可以确定你怀疑的Activity是否泄漏了,那么怎样找到泄漏的准确位置呢?
这就用到另外一个工具MAT了

3 查找原因

  1. Mat打开转换后的.hprof文件->Histogram视图

  2. 搜索要查找的类如MainActivity(relgex),搜索(Regex -enter键),右键搜索结果,List objects(查看被谁引用和引用了谁),选择with incoming references查看被引用情况
    在这里插入图片描述

  3. 分析技巧:排除容易被回收的(软引用、虚引用、弱引用),右键搜索结果,
    Path To GC Roots - exclude all phantom/weak/soft etc. references
    在这里插入图片描述
    最终我们找到了不能被回收导致Activity泄漏的地方

  4. 解决方法:Activity的onStop清除监听 ListenerCollector.clearListeners();

  5. Demo:ListenerActivity

四 MAT进行对比查找

选中一个.hprof文件,点击Navigation History - 选中histogram-Add to Compare Basket ,再选中另一.hprof文件重复操作;然后右上角compare the results

在这里插入图片描述
找到对应的Activity,看看是否泄漏
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值