LeakCanary源码分析第二讲-RefWatcher详解

如果你已经阅读了LeakCanary源码分析第一讲,那么LeakCanary的基本架构应该已经掌握了。本文将详细分析RefWatcher的工作原理,当RefWatcher检查到引用路径不是弱通路的时候就会触发HeapDumper

WeakReference和ReferenceQueue

要理解RefWatcher的工作原理,首先需要知道WeakReference。当GC线程扫描它所管辖的内存区域时,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否(这一点与SoftReference不同),都会回收它的内存。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。 WeakReference_obj WeakReference和ReferenceQueue联合使用,如果弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。上图中的实线a表示强引用,虚线aa表示弱引用。如果切断a,那么Object对象将会被回收。正如下面这段测试代码所示。

当垃圾回收器回收对象的时候,aa这个弱引用将会入队进入ReferenceQueue,所以queue.poll()将不会为空,除非这个对象没有被垃圾回收器清理。

执行这段代码,你将会看到一句打印。类似于:java.lang.ref.WeakReference@2352544e

RefWatcher工作原理

如果将上述代码第四行注释掉,会得到什么结果呢?答案肯定是没有任何输出,因为,如果a!=null那么就存在强引用指向a对象,垃圾回收器自然不会回收它,也就不会将aa这个弱引用入队。这就是RefWatcher的核心工作原理。

RefWatcher核心代码

代码已经注释了,只要你了解了WeakReference的原理,其实非常简单。这里就不详细分析了。剩下的工作就是交给HeapAnalyzer分析对象的最短强引用路径了。这将在下一篇文章中进行分析。

RefWatcher工作流程

  • RefWatcher.watch() 创建一个 KeyedWeakReference 到要被监控的对象。
  • 然后在后台线程检查引用是否被清除,如果没有,调用GC。
  • 如果引用还是未被清除,把 heap 内存 dump 到 文件系统中的一个 .hprof 文件中。
  • 在另外一个进程中,HeapAnalyzerService 通过 HeapAnalyzer 使用HAHA 解析这个文件。
  • 得益于唯一的 reference key, HeapAnalyzer 找到 KeyedWeakReference,定位内存泄漏。
  • HeapAnalyzer 计算 到 GC roots 的最短强引用路径,并确定是否泄漏。如果是,建立导致泄漏的引用链。
  • 引用链传递到 APP 进程中的 DisplayLeakService, 并以通知的形式展示出来。

LeakCanary_flow

总结

本篇文章虽然是讲RefWatcher的工作原理,其实重点讲解了WeakReference。如果你对Java对象的引用类型还不了解,那么请一定要去学习充电了。



  copyright@黑月神话,转载请注明出处:vjson.com

LeakCanary源码分析第二讲-RefWatcher详解》上有4条评论

发表评论