这琅绫擎涉及到两个新的对象: AndroidHeapDumper 和 AndroidWatchExecutor ,前者用来 dump 堆内存状况的,后者则是用来 watch 一个引用的监听器。具体道理后面再看。总之,这里已经生成好了一个 RefWatcher 对象了。
如今再看膳绫擎>
可以看到,它起首把我们传入的 activity 包装成了一个 KeyedWeakReference (可以临时算作一个通俗的 WeakReference),然后 watchExecutor 会去履行一个 Runnable,这个 Runnable 会调用 ensureGone(reference, watchStartNanoTime) 函数。
看这个函数之前猜测下,我们知道 watch 函数本身就是用来监听 activity 是否被正常收受接收,这就涉及到两个问题:
- 何时去检查它是否收受接收?
- 若何有效地检查它真的被收受接收?
所以我们认为 ensureGone 函数本身要做的事正如它的名字,就是确保 reference 被收受接收掉落了,不然就意味着内存泄漏。
核心函数:ensureGone(reference) 检测收受接收
下面来看这个函数实现:
这里先来解释锫 WeakReference 和 ReferenceQueue 的工作道理。
1.弱引用 WeakReference
被强引用的对象就算产生 OOM 也永远不会被垃圾收受接收机收受接收;被弱引用的对象,只要被垃圾收受接收器发明就会急速被收受接收;被软引用的对象,具备内存敏感性,只有内存不足时才会被收受接收,常用来做内存敏感缓存器;虚引用则随便率性时刻都可能被收受接收,应用较少。
2.引用队列 ReferenceQueue
我们常用一个 WeakReference<Activity> reference = new WeakReference(activity); ,这里我们创建了一个 reference 明天将来引用到某个 activity ,当这个 activity 被垃圾收受接收器收受接收后,这个 reference 会被放入内部的 ReferenceQueue 中。也就是说,大年夜队列 ReferenceQueue 掏出来的所有 reference ,它们指向的┞锋实对象都已经成功被收受接收了。
在一个 activity 传给 RefWatcher 时会创建一个独一的 key 对应这个 activity,该key存入一个集合 retainedKeys 中。也就是说,所有我们想要不雅测的 activity 对应的独一 key 都邑被放入 retainedKeys 集合中。
基于我们对 ReferenceQueue 的懂得,只要把队列中所有的 reference 掏出来,并把对应 retainedKeys 里的key移除,剩下的 key 对应的对象都没有被收受接收。
- ensureGone 起首调用 removeWeaklyReachableReferences 把已被收受接收的对象的 key 大年夜 retainedKeys 移除,剩下的 key 都是未被收受接收的对象;
- if (gone(reference)) 用来断定某个 reference 的key是否仍在 retainedKeys 里,若不在,表示已收受接收,不然持续;
- gcTrigger.runGc(); 手动出发 GC,急速把所有 WeakReference 引用的对象收受接收;
- removeWeaklyReachableReferences(); 再次清理 retainedKeys,如不雅该 reference 还在 retainedKeys里 (if (!gone(reference))),表示泄漏;
- 应用 heapDumper 把内存情况 dump 成文件,并调用 heapdumpListener 进行内存分析,进一步确认是否产生内存泄漏。
- 如不雅确认产生内存泄漏,调用 DisplayLeakService 发送通知。
内存泄漏检测小结
大年夜膳绫擎我们大年夜概懂得了内存泄漏检测机制,大年夜概是以下几个步调:
推荐阅读
Linux 用户可能经常碰到的一个问题是,机械有 16GB 内存之多,运行的过程也不多,然则剩下的 free 内存并不多,大年夜部分都被 buff 和 cache 占用了(比如下面我的 PC)。$ free -h >>>详细阅读
本文标题:带你学开源项目:LeakCanary-如何检测 Activity 是否泄漏
地址:http://www.17bianji.com/lsqh/35385.html
1/2 1