笔记内存泄漏检查库——LeakCanary

Posted Jason Zhang~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了笔记内存泄漏检查库——LeakCanary相关的知识,希望对你有一定的参考价值。

简介

说到检测内存泄漏,大部分人首先想到的肯定就是在github上star数20k+的开源库LeakCanary了。该开源库由Square公司开源提供,Square是美国一家移动支付公司,android开发者熟悉的okhttp、retrofit库也都是出自Square公司。
github地址:https://github.com/square/leakcanary。在这里大家能得到最新的版本以及该库的使用说明等。该库的介绍就是:

A memory leak detection library for Android and Java.

在README.md文档中也给出了库的导入方式,而它的使用方式也是出其的简单(在工程的Application类中满足条件时调用install方法即可):

public class ExampleApplication extends Application 

  @Override public void onCreate() 
    super.onCreate();
    if (LeakCanary.isInAnalyzerProcess(this)) 
      // This process is dedicated to LeakCanary for heap analysis.
      // You should not init your app in this process.
      return;
    
    LeakCanary.install(this);
    // Normal app init code...
  

标记排除的内存泄漏

事实上,Android原生系统或者被各大厂商修改过的Android系统(如华为、魅族、三星、小米等)本身就存在着一些泄露,而作为开发者我们能做的只是查找且修复由我们的代码造成的内存泄漏问题,所以我们应该只关心我们代码导致的问题。
而在实际使用中,我的华为测试机一天能产生一百多个内存泄漏,如果挨个检查是属于系统导致的的泄露还是属于该app代码导致的泄露也是一件很抓狂的事。而且有部分泄露可能是之前检查出了属于已知的,可能正在解决中,这些也不需要再去挨个点击查看详情。还好,LeakCanary也考虑到了这方面,所以给我们提供了解决方案。
上面说过LeakCanary库的使用方式核心核心代码就调用了一个install方法:

  /**
   * Creates a @link RefWatcher that works out of the box, and starts watching activity
   * references (on ICS+).
   */
  public static RefWatcher install(Application application) 
    return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
        .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
        .buildAndInstall();
  

在这个方法中我们能看到调用了excludedRefs方法,里面使用了一个叫做AndroidExcludedRefs的类。
ExcludedRefs类是LeakCanary用来标记某些想忽略的内存泄漏的,而AndroidExcludedRefs类是一个集合,里面放了一些已知的Android系统造成的内存泄漏的配置。
但是AndroidExcludedRefs也是不断在更新添加新的系统的内存泄漏的,所以可能有一些系统的内存泄露还未添加进去,尤其是某些特定改版Android系统的。另外有些我们已知的,在解决或者放弃解决的也想进行标记排除,那么该如何做呢?既然我们知道install方法执行了什么方法,那么我们通过查看它方法内操作的源码能了解到排除的类其实有多个集合来不断增加新的排除规则。(有点建造者模式的理念,关于建造者模式,多年前曾简单写过一篇介绍:https://blog.csdn.net/xiaoyu_93/article/details/52982842

    ExcludedRefs excludedRefs = AndroidExcludedRefs.createAppDefaults() // https://github.com/square/leakcanary/issues/572
            .instanceField("android.view.inputmethod.InputMethodManager", "sInstance")
            .instanceField("android.view.inputmethod.InputMethodManager", "mLastSrvView")
            .instanceField("com.android.internal.policy.PhoneWindow$DecorView", "mContext")
            .build();

    LeakCanary.refWatcher(application)
            .listenerServiceClass(DisplayLeakService.class)
            .excludedRefs(excludedRefs)
            .buildAndInstall();

如上述代码所示,就是不直接调用install方法,而是自己写方法进行初始化,可以添加额外的规则,代码中所述是guthub上issues所给出来的一个额外的基础的需要排除的,大家实际中可以再自己追加。

说明:1、instanceField方法添加某个类的某个普通变量,还有其他方法,如staticField则是添加某个类的静态变量等。
2、AndroidExcludedRefs里面虽然加入了不少系统的内存泄露,但是仔细看代码会发现install方法使用的createAndroidDefaults方法里面只加入了五个所有Android系统都会产生的泄露,所以,因为我使用华为测试机,我需要额外自己去加不少其他的来过滤掉特定系统会造成的泄露。千万不要以为官方的这个方法已经帮我们排除了全部或者大部分,实际上,仅仅排除了五个所有Android系统上都会出现的而已。所以AndroidExcludedRefs类大家参考参考即可。
3、网上资料说AndroidExcludedRefs内的是白名单,不会提示出来,但测试发现其实还是会提示出来(1.6.1版本库,测试手机华为荣耀8.0系统),只不过item项会有【Excluded】标识,则我们可以忽略不去点击查看具体详情。

以上是关于笔记内存泄漏检查库——LeakCanary的主要内容,如果未能解决你的问题,请参考以下文章

由浅入深,详解 LeakCanary 的那些事

LeakCanary:简单粗暴的内存泄漏检測工具

由浅入深,详解 LeakCanary 的那些事

Android实战——LeakCanary检测内存泄漏

如何使用模块化代码片段中的LeakCanary检测内存泄漏?

了解 LeakCanary 内存泄漏堆栈跟踪