Android内存泄漏的检测工具——LeakCanary

 

首先了解什么是内存泄露

http://liuwangshu.cn/application/performance/ram-3-memory-leak.html

 

1Leakcancary的优势

LeakCanary是一个可视化的内存泄露分析工具他具备以下优势

· 简单:只需设置一段代码即可,打开应用运行一下就能够发现内存泄露。而MAT分析需要Heap Dump,获取文件,手动分析等多个步骤。

· 易于发现问题:在手机端即可查看问题即引用关系,而MAT则需要你分析,找到Path To GC Roots等关系。

· 人人可参与:开发人员,测试测试,产品经理基本上只要会用App就有可能发现问题。而传统的MAT方式,只有部分开发者才有精力和能力实施。

 

 

2. 使用说明

2.1 在build.gradle中添加依赖

首先,在必须在对应的app模块的gradle添加对应的库,在其他module模块添加无效

dependencies {
   
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.4'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.4'

}

 

到这里,就添加了对他的依赖。这里说明一下,使用其他版本可能会因为版本问题导致报错,建议使用最新版本,也就是这个1.5.4

2.2 在application中配置 


public class BaseApplication extends Application {

    private RefWatcher refWatcher;
    @Override
    public void onCreate() {
        super.onCreate();
        refWatcher= setupLeakCanary();//2
    }
    private RefWatcher setupLeakCanary() {
        if (LeakCanary.isInAnalyzerProcess(this)) {
            return RefWatcher.DISABLED;
        }
        return LeakCanary.install(this);//1
    }

    public static RefWatcher getRefWatcher(Context context) {
        BaseApplication leakApplication = (BaseApplication) context.getApplicationContext();
        return leakApplication.refWatcher;
    }
}

在注释2处,,完成对LeakCancary的安装,经过以上两个步骤,你的手机界面出现

 

这个黄色的图标就是我们的监控工具

 

2.3 检测activity内存泄漏问题,原理是application中监控着所有activity生命周期在activity的onDestory中


@Override
protected void onDestroy() {
    super.onDestroy();
    RefWatcher refWatcher = BaseApplication.getRefWatcher(this);//1
    refWatcher.watch(this);
}

Activity生命周期结束的时候,如果你的activity发生内存泄漏,状态栏会提示你

 

那么,黄色的应用  Leaks中

 

会把内存泄漏的详情告诉你,像这里就是因为我的TestActivity中开了LeakThread这个线程,造成了内存泄漏

泄漏内存是115kb

 

2.4 监控的对象当我们需要对某个对象进行监控时,


BaseApplication.getRefWatcher().watch(sleaky)

 

其中sleaky就是我们要检测的对象

那么,哪些是需要我们检测的对象呢

默认情况下,是对Activity进行了检测。另一个需要监控的重要对象就是Fragment实例。因为它和Activity实例一样可能持有大量的视图以及视图需要的资源

其他也可以监控的对象

BroadcastReceiver ,Service 其他有生命周期的对象直接间接持有大内存占用的对象(即Retained Heap值比较大的对象)

何时进行监控

首先,我们需要明确什么是内存泄露,简而言之,某个对象在该释放的时候由于被其他对象持有没有被释放,因而造成了内存泄露。

因此,我们监控也需要设置在对象(很快)被释放的时候,如Activity和Fragment的onDestroy方法。

一个错误示例,比如监控一个Activity,放在onCreate就会大错特错了,那么你每次都会收到Activity的泄露通知。

 

 

 

以上就是LeakCancary的使用方法

3.LeakCanary的原理

  • Android 应用的整个生命周期由其组件的生命周期组成,如下图中所示。用户使用应用的过程中,在不同界面之间跳转,每个界面都经历着”生死“的转换,可在此建立检测点。Activity/Fragment 都有 onDestory() 回调方法, 进入此方法后,Activity/Fragment生命周期结束,应该被回收。

简述声明周期

  • 然后我们需要解决:如何得到未被回收的对象。ReferenceQueue+WeakReference+手动调用 GC可实现这个需求。

    WeakReference 创建时,传入一个 ReferenceQueue 对象。当被 WeakReference 引用的对象的生命周期结束,一旦被 GC 检查到,GC 将会把该对象添加到 ReferenceQueue 中,待ReferenceQueue处理。当 GC 过后对象一直不被加入 ReferenceQueue,它可能存在内存泄漏。

获得未被回收的 Object

  • 找到了未被回收的对象,如何确认是否真的内存泄漏?这里可以将问题转换为:未被回收的对象,是否被其他对象引用?找出其最短引用链。VMDebug + HAHA 完成需求。

    VM 会有堆内各个对象的引用情况,并能以hprof文件导出。HAHA 是一个由 square 开源的 Android 堆分析库,分析 hprof 文件生成Snapshot对象。Snapshot用以查询对象的最短引用链。

解析hprof

  • 找到最短引用链后,定位问题,排查代码将会事半功倍。

如下泳道图分析, LeakCanary 各个模块如何配合达到检测目的。

泳道图

猜你喜欢

转载自blog.csdn.net/qq_39037047/article/details/79563423