简介
LeakCanary是一款开源的内存泄漏检查工具,在项目中,可以使用它来检测Activity是否能够被GC及时回收。github的地址为https://github.com/square/leakcanary
使用方式解析
将LeakCanary引入AS,在Application中调用如下方法,可以跟踪Activity是否被GC回收。
![img_fb051df4397dc7e08201919031c5b5ea.png](https://i-blog.csdnimg.cn/blog_migrate/3a480e7ae812230d8bd7c7270ccf6382.png)
LeakCanary.install()方法的调用流程如下所示:
![img_22168ccdfd1ea29fe96f6281371d1aa7.png](https://i-blog.csdnimg.cn/blog_migrate/21dabaf8cd63e3af5be50b8c0b52f3d9.png)
Install方法如下:
![img_4375bba824bf57c4e6ecb29f7422cdc8.png](https://i-blog.csdnimg.cn/blog_migrate/a5e8a02766df7c112eceff5e33d62379.png)
其中listenerServiceClass方法传入了展示分析结果的Service(DisplayLeakService);excludedRefs方法排除了开发中可以忽略的泄漏路径;buildAndInstall是主要的函数,实现了activity是否能被释放的监听。
![img_ef18735d35885411a708c2f43ab70af3.png](https://i-blog.csdnimg.cn/blog_migrate/64e0677122046cb8132884504e1cc6cd.png)
buildAndInstall会调用ActivityRefWatcher.install来监测Activity。
![img_7183192e2601a48ca3d253d76930bd36.png](https://i-blog.csdnimg.cn/blog_migrate/46601a3650a132a88eeaaace49d4f569.png)
最终调用了watchActivities():
![img_f453acfeb316d36001910bf8b94b3e29.png](https://i-blog.csdnimg.cn/blog_migrate/f3f0d755535ddb0b1442f9b1f00e6644.png)
通过registerActivityLifecycleCallbacks来监听Activity的生命周期:
![img_22fd5490d0824810d8d8108f50032982.png](https://i-blog.csdnimg.cn/blog_migrate/32da0b3644e06027ae95ef16ab54a6e4.png)
lifecycleCallbacks监听Activity的onDestroy方法,正常情况下activity在onDestroy后需要立即被回收,onActivityDestroyed方法最终会调用RefWatcher.watch方法:
![img_7263c38de8ee87bd681b719301d47fab.png](https://i-blog.csdnimg.cn/blog_migrate/402534aa6087f1362fb8e3c6f2322e29.png)
监测机制利用了Java的WeakReference和ReferenceQueue,通过将Activity包装到WeakReference中,被WeakReference包装过的Activity对象如果被回收,该WeakReference引用会被放到ReferenceQueue中,通过监测ReferenceQueue里面的内容就能检查到Activity是否能够被回收。检查方法如下:
![img_e8dc0e1707cd696ac22554a4174a7ae4.png](https://i-blog.csdnimg.cn/blog_migrate/888a550539de6f86a612341228078ab2.png)
1、 首先通过removeWeaklyReachablereference来移除已经被回收的Activity引用
2、 通过gone(reference)判断当前弱引用对应的Activity是否已经被回收,如果已经回收说明activity能够被GC,直接返回即可。
3、 如果Activity没有被回收,调用GcTigger.runGc方法运行GC,GC完成后在运行第1步,然后运行第2步判断Activity是否被回收了,如果这时候还没有被回收,那就说明Activity可能已经泄露。
4、 如果Activity泄露了,就抓取内存dump文件(Debug.dumpHprofData)
![img_9681ba0595caebc9be4db78f91c6e0d7.png](https://i-blog.csdnimg.cn/blog_migrate/adfc4fd2fdab7d32e12c303f3c2bfab6.png)
5、 之后通过HeapAnalyzerService.runAnalysis进行分析内存文件分析
![img_cf815812302d0deb81d83129dff204bb.png](https://i-blog.csdnimg.cn/blog_migrate/7f15b4d2b776423119756c6eb9b0c377.png)
接着通过HeapAnalyzer(checkForLeak—findLeakingReference---findLeakTrace)来进行内存泄漏分析。
6、 最后通过DisplayLeakService进行内存泄漏的展示。