LeakCanary如何工作
一旦安装了LeakCanary,它就会按照以下4个步骤自动检测和报告内存泄漏
检测持有对象
转储堆。
分析堆。
对泄漏进行分类。
1. 检测持有对象
LeakCanary与Android生命周期想关联,自动检测Activity和Fragment何时被销毁,何时应该被垃圾回收。这些被销毁的对象被传递给ObjectWatcher,该ObjectWatcher持有对它们的弱引用。LeakCanary会自动检测以下对象的泄漏:
销毁的
Activity实例销毁的
Fragment实例销毁的
View实例ViewModel实例
您可以观看任何不再需要的对象,例如一个分离的视图或一个被破坏的演示器。
AppWatcher.objectWatcher.watch(myDetachedView, "View was detached")如果ObjectWatcher持有的弱引用在等待5秒并运行垃圾回收后没有被清除,被监视的对象就会被认为是被持有,并且有可能泄漏。LeakCanary将此记录到Logcat。
D LeakCanary: Watching instance of com.example.leakcanary.MainActivity
(Activity received Activity#onDestroy() callback)
... 5 seconds later ...
D LeakCanary: Scheduling check for retained objects because found new object
retainedLeakCanary等待保留对象的计数达到阈值后才会转储堆,并显示最新计数的通知。

默认的阈值是当应用可见时保留5个对象,当应用不可见时保留1个对象。如果您看到保留对象通知,然后将应用程序置于后台(例如按下主页按钮),那么阈值从5变为1,LeakCanary会在5秒内转储堆。点击通知会迫使LeakCanary立即转储堆。
2.转储堆
当保留对象的数量达到阈值时,LeakCanary会将Java堆转储到一个存储在Android文件系统上的.hprof文件(堆转储)中(参见LeakCanary在哪里存储堆转储?转储堆会使应用程序冻结很短的时间,在此期间,LeakCanary会显示以下Toast。

3.分析堆
LeakCanary使用Shark解析.hprof文件,并定位该堆转储中保留的对象。

对于每个保留的对象,LeakCanary会找到防止该保留对象被垃圾回收的引用路径:它的泄漏跟踪。你将在下一节学习分析泄漏跟踪。修复内存泄漏。

当分析完成后,LeakCanary会显示一个带有摘要的通知,并在Logcat中打印结果。请注意下面的4个保留对象是如何被归为2个不同的泄漏的。LeakCanary 为每个泄漏跟踪创建一个签名,并将具有相同签名的泄漏分组在一起,即由相同错误引起的泄漏。

点击通知会打开一个Activity,提供更多细节。稍后通过点击LeakCanary启动器图标再次回到它。

每一行对应于一组具有相同签名的泄漏。LeakCanary在应用程序首次触发具有该签名的泄漏时,将某行标记为 "New"。

点击一个泄漏物,打开一个有泄漏痕迹的屏幕。你可以通过下拉菜单在保留的对象和它们的泄漏痕迹之间进行切换。

泄漏签名是涉嫌导致泄漏的每个参考文献的连接的哈希值,即每个参考文献用红色下划线显示。

当泄漏跟踪以文本形式共享时,这些同样可疑的引用会用~~~来下划线。
在上面的例子中,泄漏的签名将被计算为:
4.泄露分类
LeakCanary 将它在您的应用程序中发现的泄漏分为两类。应用程序泄漏和库泄漏。库泄漏是由您无法控制的第三方代码中的已知错误引起的泄漏。这种泄漏影响了您的应用程序,但不幸的是,修复它可能不在您的控制范围内,所以LeakCanary将其分离出来。
在Logcat打印的结果中,这两类是分开的。
LeakCanary在其泄漏名单中,将一行人标记为图书馆泄漏。 
LeakCanary 提供了一个已知泄漏的数据库,它通过参考名称的模式匹配来识别。例如:
最后更新于