1. leakcanary配置使用
参考LeakCanary中文翻译文档LeakCanary 中文使用说明。
2. 原理图
3. 过程解析
RefWatcher.watch() 创建一个 KeyedWeakReference 到要被监控的对象。
然后在后台线程检查引用是否被清除,如果没有,调用GC。
如果引用还是未被清除,把 heap 内存 dump 到 APP 对应的文件系统中的一个 .hprof 文件中。
在另外一个进程中的 HeapAnalyzerService 有一个 HeapAnalyzer 使用HAHA 解析这个文件。
得益于唯一的 reference key, HeapAnalyzer 找到 KeyedWeakReference,定位内存泄漏。
HeapAnalyzer 计算 到 GC roots 的最短强引用路径,并确定是否是泄漏。如果是的话,建立导致泄漏的引用链。
引用链传递到 APP 进程中的 DisplayLeakService, 并以通知的形式展示出来。
4. leakcanary log
log解析日志包含的内容
- GC ROOT:最短引用路径信息,一般我们只需关注这块信息即可.注:一般display的内容只有GC ROOT的信息。
- 设备信息: 介绍设备信息,以及泄露内存的大小。
- Details:详细说明GC ROOT 引用信息。
- Excluded Refs:过滤掉的泄露信息。
注:上图展示的信息是将leak info信息保存到文件显示的内容。关注的信息
拿到log我们只需关注GC ROOT 引用信息即可。一般80-90%都可以从这里定位到问题。
排除SDK已添加过滤的内存泄漏
如果GC ROOT内容包含”NO LEAK FOUND“或者”EXCLUDEED XX“字样,可以直接不用处理,一般这些代表没有找到内存泄漏信息或者是LeakCanary已经排除SDK泄漏的字样,可以直接不做处理。- GC ROOT没有具体泄漏信息 ,如何定位?
- SDK或者第三方库泄漏导致
复制GC ROOT相关信息Google,查看下是否是SDK或者第三方库泄漏导致,如果确实是,反馈给LeakCanary维护者,将其添加到过滤文件,更新LeakCanary库即可。如果不是进行下面步骤。 - 非SDK或者第三方库泄漏导致
可能是由于LeakCanary确实信息没有统计到,尝试解析对应的源文件.hprof,进行详细查看信息,确认内存泄漏,.hprof文件分析参考MAT-实用篇。
注:官方leakcanary源文件.hprof一般生成在SDcard 的Download文件夹下,最大保存个数默认为7个。 - 具体界面已经定位,尝试连续操作此界面,尝试手动复现此泄漏或者用Memory Profiler/Heap Viewer分析占内存的对象。
- SDK或者第三方库泄漏导致