LeakCanary内存泄漏检测工具

  • 首先来说一下我再项目中遇到的内存泄漏的问题:
    公司一个上线很久的项目突然有用户反馈使用程序时间就了手机就变得很卡。额,这不是内存泄漏嘛!但是由于这个旧项目不是笔者开发并且没有改过其中的问题。突然来一任务就要解决内存泄漏的问题,当时笔者内心是很拒绝的,但是身为一个负责任的程序员就不能说“不”。之前用过LeakCanary检测内存泄漏,这次依然使用的是LeakCanary。不检测不知道一检测吓一跳,程序刚运行起来没两分钟LeakCanary就开始提示内存泄漏了,再使用一会儿,泄漏提示已经10多条了,这是什么鬼,打开提示看的我也是一头露水到处都是泄漏。如此之多的泄漏难道是封装Base出现的问题,经过分析确实是这个原因,但是项目中有一点我不是很理解“项目搭建框架是一个Activity+多个Fragment,这么也是没毛病的啊,但是不知为啥每个Fragment切换又重新启动Activity,并且返回操作也是startActivity ”这一点我一直没有看明白,不知道有没有了解的大神能给讲解一下!最后的问题呢就是一直startActivity但是没有执行finish,所以Activity一直被创建。一直创建的结果就是OOM了!

    LeakCanary的使用

  • 想了解关于LeakCanary更多的朋友们可以 https://github.com/square/leakcanary 了解更多哦!
    1、Android Studio 集成 需要在app的build.gradle - dependencies中添加

    //debug
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
    //release
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
    //项目中如果有Fragment需要检测那么就需要
    debugImplementation 'com.squareup.leakcanary:leakcanary-support-fragment:1.6.3'

2、初始化
需要在Application的onCreate中添加


if (LeakCanary.isInAnalyzerProcess(this)) {
     //a
      return;
    }
    //b
LeakCanary.install(this);

LeakCanary 是通过开启独立进程的方式观察应用内存的,那么a处判断的就是当前的进程是属于LeakCanary开启的独立进程,如果是返回不进行内存分析,否则就是应用进程 通过调用LeakCanary.install(this);来初始化;
就这简单的两步就集成成功到此分析Activity的内存泄漏就可以了,但是如果项目中存在Fragment那么就需要在Fragment的onDestroy()中添加watch监听Fragment中的对象。通常我们都是在BaseFragment中添加。

refWatcher.watch(this);

那么这个refWatcher 从哪里来呢,其实这个就是LeakCanary.install(this);的返回值,我们只需要在BaseFragment中引用Application中的RefWatcher即可!
到此万事俱备只等“泄漏”了!
3、那么如何分析具体发生内存泄漏的位置呢!
LeakCanary内存泄漏检测工具_第1张图片
通过引用连我们发现HttpResponseListener 引用mActivity导致BlankActivity 一直没有被销毁!定位到了相关点具体定位那么就需要根据项目代码分析了!
那么LeakCanary具体的分析原理是什么呢?
原理:
一个Activity执行完onDestroy()之后,将它放入WeakReference中,然后将这个WeakReference类型的Activity对象与ReferenceQueque关联。这时再从ReferenceQueque中查看是否有没有该对象,如果没有,执行gc,再次查看,还是没有的话则判断发生内存泄露了。最后用HAHA(square 开源的 Android 堆分析库)去分析dump之后的heap内存。
分析步骤:

  1. RefWatcher.watch()会创建一个keyedWeakReference用于观察对象;
  2. 在后台线程中检测引用的对象是否清除回收,同时触发GC,查看是否回收;
  3. 如果引用仍然没有被清除回收那么就把堆栈中的信息保存到.hprof文件中;
  4. HeapAnalyzerService(也就是观察对象回收的服务)开启在一个独立进程中,并且使用HAHA开源库解析指定时刻的堆栈信息快照 heap dump;
  5. 从堆栈快照中 HeapAnalyzer 根据一个独特的key找到KeyedWeakReference 并定位内存泄漏;
  6. HeapAnalyzer 为了确定内存泄漏,计算了GC Root 的最短引用路径,然后建立导致内存泄漏的链式引用;(也就是Leak Canary 日志打印的引用);
  7. 将结果传到App进程中的DisplayLeakService,到此一个内存泄漏的通知便产生;

问题:因为文件分析以及日志导入所以需要添加一下读写权限;

关于LeakCanary源码的分析推荐大家观看 https://jsonchao.github.io/

你可能感兴趣的:(性能优化,内存泄漏)