LeakCanary 核心源码解析,android 开发从入门到精通素材
看源码还是那句话,先找入口,顺着入口看主流程。
LeakCanary 监听 Activity 的 onDestory 方法,然后介入,所以从这里开始
发现入口在 RefWatcher.watch 方法里,这个 RefWatcher 是核心类,跟进去 watch 方法。
可以看出这里开始搞事情了,先解释一下这些变量的意义
这样就可以解释,上图 watch 方法里面的操作了
使用 randomUUID 生成一个随机数 key,并加到了一个 set 中,这个 key 跟当前监控的 activity 是一一对应的,这个很关键,watchedReference 就是当前关闭的 activity 对象,然后包装成 KeyedWeakReference 对象,KeyedWeakReference 继承了 WeakReference。
后续就是就操作这个 KeyedWeakReference 这个弱引用。
到了这里就不得不提一下,强软弱虚这四个东西,如果还有不懂的小伙伴,还是要去看一下的,这里只提一下弱引用,简单来说就是
。
弱引用持有的对象被回收了,那么弱引用就会放到与之关联的引用队列中。
???
讲人话!那举个栗子
就是上面 watch 方法的 watchedReference(就是那个被监测的 activity)被 KeyedWeakReference 弱引用持有了,当 activity 被回收了,RefWatcher#queue 里面就会有这个 KeyedWeakReference。
反之如果一顿操作之后 queue 都没有这个 KeyedWeakReference,说明 activity 没有被回收,那么就判定为内存泄漏。
这也是 LeakCanary 的核心思想。
好,接着 watch 方法往下走,ensureGoneAsync 方法跟进去到一个 ensureGone 的核心方法里
红框这里是核心中的核心。看起来很短,但浓缩才是精华。
removeWeaklyReachableReferences 方法里就是遍历把引用队列 queue 里的对象,在 retainsKeys 这个 set 里面移除掉。
讲了半天,还记得开头这个 retainsKeys 放的什么吗?是那个 UUID 生成的与每个 activity 一一对应的 key,可以理解为 activity 对应的一个值。当队列有一个弱引用了,说明有一个对应 activity 被回收了。
gone 方法里判断 retainsKeys 集合里还有没有这个 activity 对应的值,没有说明正常回收了。
ensureGone 的整个流程基本就清楚了,理一下 ensureGone 的流程。
首先根据队列的对象,移除对应 set 里对应的 key 值,gone 判断是否移除成功,成功返回 DONE,没有泄露结束流程,gone 判断还存在,原谅 ta 再给一次机会,调用 runGc 触发回收,再次移除 key 值,gone 判断还存在,不好意思,没有机会了,使用 heapDumper.dumpHeap 出调用链,showNotification 展示到通知栏,最后展示到 DisplayLeakActivity 页面上。
评论