天天看点

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

说明:如果只是单存的内存抖动,AndroidStudio的Memory Profiler就可以分析了,具体分析过程已经有很多文章说明了,这里就不赘述,接下来要说的是内存泄露的追查。

1.MAT下载

MAT 下载地址:https://www.eclipse.org/mat/downloads.php

下载版本:

Mac OSX (Mac/Cocoa/x86_64)

2.MAT安装和启动

下载完成,在Downloads目录下找到

MemoryAnalyzer-1.9.0.20190605-macosx.cocoa.x86_64.zip

解压文件,得到

mat.app

目录。移动到自己的目录下执行 /xxxxx/mat.app/Contents/MacOS/MemoryAnalyzer -data ./workspace

输入命令行 : /Users/mac/Desktop/mat/mat.app/Contents/MacOS/MemoryAnalyzer -data ./workspace

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

看到欢迎界面就是成功了。

这是一款用于内存分析的工具,主要可以对内存泄露(OOM之前)的问题进行分析和定位。配合Memory Profiler分析内存泄露导致的卡顿和线上偶发性的崩溃。

由于我们的app中有一些写的不合适的代码片段,导致内存的分配非常频繁,在频繁的分配和GC的情况下就会出现内存抖动。当我们使用static不注意的时候就很容易造成 对外部类的强引用,即使不调用不崩溃,但是由于static和app的生命周期相同,所以强引用的对象无法释放,导致内存无法清理,由于每一个app所分配的内存是有限的,所以就会导致内存泄露,当泄露到一定程度,剩余内存或者内存碎片不足以分配的时候就会OOM,崩溃,这就是线上崩溃线下无法复现的问题的来源。

分析步骤:

1.当我们看到页面卡顿

比如我们新建一个回调,内部包含static静态变量,然后里面也传入了Context,假设在Activity的OnClick时间内构造它,那么每一次构造都会有Context - XXXActivity对象被保存在这个回调的内部,那么每一次finish都不会释放。

当我们打开AndroidStudio的Memory Profiler的时候我们就可以在Memory里面看到成阶梯状的内存消耗的趋势。这个时候我们通过内存变化曲线(阶梯状)可以判断内存存在泄漏。

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

我们只需要把我们认为有泄漏的部分,进行堆转储,导出文件即可

(华为手机 eg P40,当我们使用Memory Profiler的时候会闪退,可能是ROM架构的问题)

接下来,将导出文件转换:

hprof-conv /xxxx/memory_leak.hprof /xxxxx/memory_leak_transed.hprof  不执此命令MAT不能处理堆转储文件

1.打开文件

点击Histogram

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

2.匹配搜索需要的类的名称

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)
App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

我们可以看见有一个Activity存在存在七个对象 这是不合理的

那么来看看都是谁强引用了吧

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

看见了七个强引用

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

选择一个对象  去除软引用 只关注强引用 也可以直接看with all references

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

查看强引用结果的依赖路径

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

我们可以看见是EventBus中持有了上下文的引用看看源码

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

销毁的时候写错了,应该改成

@Override
protected void onDestroy() {
    super.onDestroy();
    if (EventBus.getDefault().isRegistered(this)) {
        //取消注册
        EventBus.getDefault().unregister(this);
    }
}
           

这样就释放了。虽然只是一个复制粘贴的问题,但是却真实的影响了性能,不会崩溃,在线上是一个很恶心的bug,反馈到研发这里只是偶现。这就是通过内存分析查找问题的方法 MAT+MemoryProfiler

前后对比

App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)
App体系化优化之内存优化(Memory Analyzer Tool + Memory Profiler)

可以看见内存得到了释放~~~~~~~~

继续阅读