手把手带你分析LeanCancary源码
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手带你分析LeanCancary源码相关的知识,希望对你有一定的参考价值。
参考技术A LeakCancary 是一个实时监控内存泄漏的开源框架,当检测到有内存泄漏时,会以通知的方式提示开发者当前发生了内存泄漏监听activity的生命周期,在Activity的onDestory方法中,开始监听activity对象, 通过将Activity包装到WeakReference中,被WeakReference包装过的Activity对象如果被回收,该WeakReference引用会被放到ReferenceQueue中,通过监测ReferenceQueue里面的内容就能检查到Activity是否能够被回收。其中最重要的两个对象为
Set<String> retainedKeys: 存放所有监控的Activity的key(值为通过uuid,唯一标识Activity)
ReferenceQueue<Object> queue:所有被回收的activity对象会存放到这个引用队列里面, 如果想要知道一个activity有没有内存泄漏,则只需要判断该activity在
1.在build.gradle中添加依赖
至此,LeakCancary 的接入工作就完成了,是不是超简单?
我们从入口函数开始分析
首先判断当前运行的进程是否是属于HeapAnalyzerService进程,如果是 则return调,防止应用本身Application的onCreate方法多次初始化。这里需要这么做的原因是:LeakCancary本身是运行在另外一个进程中的,这点我们可以从LeakCancary的androidManifaset.xml中可以看出是有单独设置process Named的。
接下来执行 LeakCanary.install
LeakCanary.refWatcher()
通过builder模式构建了AndroidRefWatcherBuilder对象,然后通过AndroidRefWatcherBuilder对象设置了listenerServiceClass()用于绑定DisplayLeakService服务,该服务用来分析和显示内存泄漏信息的通知
AndroidRefWatchBuilder.buildAndInstall
先调用AndroidRefWatchBuilder.buid() 构建一个RefWatcher对象
构建RefWatcher的参数有
解析来是
LeakCancaryInternal.java
启动DisplayLeakActivity并显示应用图标,这个图标是LeakCancary这个应用的图标
接下来是执行 :
ActivityRefWatcher.install(context, refWatcher);
在Activity的onDestroy方法中执行RefWatcher.watch(activity)
RefWatcher.java
这里需要注意几个变量:
这里有一个知识点:弱引用和引用队列配合时,当弱引用持有的对象被垃圾回收,java虚拟机会把这个弱引用加入到与之关联的引用队列中。也就是说当activity被回收时,activity对象的引用就会被添加到ReferenceQueue这个引用队列中。
接下来是具体的内存泄漏判断过程
efWatcher.ensureGoneAsync
这里的watchExecutor 实现类是AndroidWatchExecutor
AndroidWatchExecutor.execute()
这里是切换到主线程,当消息队列空闲时执行run方法, run方法实际执行的是RefWatcher中的ensureGone()
RefWatcher.ensureGone();
遍历ReferenceQueue列表中的对象(这些对象已经被回收), 判断对象是否存在当前activity的弱引用,存在则删除retainedKeys中的activity的key 值; 如果activity没有被回收,则不会添加到ReferenceQueue,也就不会从retainedKeys中移除
2.通过gone(reference)来判断当前弱引用对应的Activity是否存在于retainedKeys?如果不存在,则说明通过第一步的操作,已经移除了该引用的key值,直接返回即可。
3.如果第二部没有返回,说明retainedKeys还存在当前activity的引用(也就是改activity没有被添加到ReferenceQueue,没有被回收),则调用GcTigger.runGc方法运行GC.
AndroidHeapDumper.dumpHeap()
调用 File heapDumpFile = leakDirectoryProvider.newHeapDumpFile(); 新建hprof文件,然后调用Debug.dumphprofData() 方法 dump 当前堆内存并写入刚才创建的文件。
然后调用heapdumpListener.analyze(heapDump)分析刚刚生成的heapDumpwen文件
这里的heapdumpListener 是ServiceHeapDumpListener
调用HeapAnalyzerService开始启动HeapAnalyzerService 这个前台服务执行分析
HeapAnalyzerService.java
调用heapAnalyzer.checkForLeak 获取结果后,调用AbstractAnalysisResultService.sendResultToListener展示分析结果。具体是通过DisplayLeakService 来展示的。
最后会执行afterDefaultHandling方法,在这里我们可以自定义一些操作,例如上报泄漏信息给服务器
LeakCancary主要是利用了弱引用 WeakReference 和 引用队列 ReferenceQueue的知识,当WeakReference中引用的对象被回收时,该引用会被添加到ReferenceQueue中,如果没有被回收,则不会添加到ReferenceQueue中。 所以可以通过检测ReferenceQueue是否存在activity的引用来判断activity是否存在泄漏导致没有回收。
LeakCanacary 监控内存泄漏主要流程如下:
参考 https://juejin.im/post/5a9d46d2f265da237d0280a3
以上是关于手把手带你分析LeanCancary源码的主要内容,如果未能解决你的问题,请参考以下文章