oynix

于无声处听惊雷,于无色处见繁花

LeakCanary分析

LeakCanary主要用在Android中分析内存泄漏。何为内存泄漏?简单说便是,当一个对象所占用堆存储空间该被系统GC回收时,却由于种种原因没有被回收,那么这些内存就称为泄漏的内存。举个例子,退出一个Activity时,这时这个Activity该被回收,但是因为Activity内声明的Thread还在跑,Thread持有Activity的引用,导致Activity无法被回收,这时就造成了内存泄漏。

LeakCanary是Square公司出品,这是家做移动支付的公司,但对于开发者来说,这就是家开源库公司,因为不少当下较为流行的三方库,都是出自Square,比如OkHttp,Retrofit,Picasso,这几个较为常用。

1. 使用

  • Github库地址
  • 文档地址
    接入十分简单,在build.gradle中,加入下面的依赖,即可
    1
    2
    3
    4
    dependencies {
    // debugImplementation because LeakCanary should only run in debug builds.
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.9.1'
    }

2. 工作步骤

当LeakCanary被安装后,它会自动检测,并报告应用中的内存泄漏,分为4个步骤:

  1. 检测存活的对象
  2. 输出堆信息
  3. 分析堆信息
  4. 将泄漏分类

2.1 检测存活对象

LeakCanary注册了Android生命周期的检测,会自动检测执行过onDestroy方法的Activity和Fragment,这些都应该被GC回收。ObjectWatcher会持有这些对象的弱引用,LeakCanary会检测下面这些对象

  • 被销毁的Activity实例
  • 被销毁的Fragment实例
  • 被销毁的Fragment View实例
  • 被清理的ViewModel实例
    如果被ObjectWatcher持有的对象,在5秒后依然没有被清理,那么就会执行GC,之后,若被持有object依然存在没有被回收,那么就有可能泄漏了。

2.2 输出堆信息

当存活的对象到达阈值的时候,LeakCanary就会将Java堆信息输出到一个.hprof文件中,这个操作可能会卡住应用一小段时间,会有Toast给出提示。

2.3 分析堆信息

Shark: Smart Heap Analytisis Reports for Kotlin,是一个分析堆信息的工具
LeakCanary使用Shark来分析hprof文件,并定位存活对象在堆信息中的位置。对于每一个存活的对象,LeakCanary都会找到阻止这个对象被系统GC回收的引用路径。当分析完成时,会有一个包含汇总信息的通知提示,点开便可查看详细信息。

2.4 泄漏分类

LeakCanary将她从应用中发现的泄漏分为两类,一类是应用自身的泄漏,一类是依赖库的泄漏。依赖库泄漏是三方库中已知的bug导致,我们无法控制。这个泄漏对我们应用产生了影响,但不幸的是,我们无法修复。

3. 总结

LeakCanary关键部分,就是如何检测泄漏对象:通过注册回调监听Activity和Fragment的生命周期,在其destroy之后,创建WeakReference,然后就是等待5秒,理想状态下这个时间内会被GC回收,如果5秒还存活,那么就手动调用GC,依然存活的就考虑是泄漏了,最后就是分析堆、查引用路径。下面这个文章对里面的代码做了分析,但是版本不是最新,和最新的可能会有一些出入,但大体逻辑是一样的。

全解系列:内存泄漏定位工具LeakCanary

------------- (完) -------------
  • 本文作者: oynix
  • 本文链接: https://oynix.com/2022/04/af8dbc800f86/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

欢迎关注我的其它发布渠道