LeakCanary是square公司发布的一款检测Activity内存泄漏的工具。项目地址
1 设计
1.1 类图
1.2 时序图
2.核心类功能介绍
2.1 LeakCanary.java
LeakCanary主要是一个工具类,构建RefWatcher
对象。
(1)主要函数
1 | public static RefWatcher install(Application application); |
第一个方法主要是初始化安装LeakCanary模块,还包括一些舒适化参数的构建。
第二个方法是通过最后分析的Dump文件和结果构建输入字符串。这个方法后面在Activity上显示会使用到。
2.2 RefWatcherBuilder.java
这个类主要是构建RefWatcher的包装类,它有个子类ActivityRefWatcher
包含一些对Android的适配, 具体方法这里忽略,可以看下面RefWatcher
包含成员变量。
2.3 ActivityRefWatcher.java
这个类主要是创建App ActivityLifecycleCallbacks
监听Activity
destory事件,然后调用RefWatcher
分析回收问题。
(1)主要函数
1 | public void watchActivities() { |
可以看到主要是通过application.registerActivityLifecycleCallbacks的方式监听Activity生命周期,然后调用refWatcher.watch(activity)
2.4 RefWatcher.java
这个类是核心类,主要分析Activity是否被回收和生成Dump文件。
(1)主要成员
1 | private final WatchExecutor watchExecutor; |
watchExecutor:执行回收和dump文件处理的线程提供者。子类有AndroidWatchExecutor
其实就是在子线程中处理。
debuggerControl: 主要判断当前APP是否以Debug模式运行。
gcTrigger:调用GC方法
heapDumper:生成内存快照文件
retainedKeys: 存放key值,每个key对应一个Activity的虚引用。
queue: 负责存放虚引用对象释放完的队列。
heapdumpListener: 处理Dump信息
excludedRefs: 忽略一个内存泄漏的方法。
(2)主要方法
1 | Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) { |
这个涉及到Java中虚引用的概念,可google详细了解。
首先直接判断Activity是否释放,如果释放直接结束,没有的话就调用系统GC,再判断Activity是否释放,如果释放直接结束,没有的话生成DumpFile,然后交给HeapdumpListener处理。
2.5 HeapAnalyzerService.java
解析DumpFile文件的后台服务
2.6 HeapAnalyzer.java
解析DumpFile文件工具类
(1)主要方法
1 | public AnalysisResult checkForLeak(File heapDumpFile, String referenceKey); |
解析过程较为复杂,有兴趣的可以了解下。主要是解析Hprof文件,GCRoots.
2.7 AnalysisResult.java
保存分析结果的存储对象。
(1)主要成员
1 | public final boolean leakFound; |
2.8 DisplayLeakService.java
主要负责通知栏提醒和保存分析结果。
2.9 其他
其他模块主要是对结果进行展示的逻辑,这里就不一一分析。
3 杂谈
1.这里是通过手动触发GC,然后判断回收,手动触发GC会打乱系统自动回收,影响APP性能,所以注意不要发布到正式包。
2.那需要思考的正式环境想统计内存泄漏问题怎么办?自己有个思路但是有缺陷
(1)开启一个线程阻塞ReferenceQueue.remove(), 然后定时(5分钟)去读取retainedKeys中的未被回收的Activity。
(2)但是Android系统回收无规律和没有事件通知,不知道系统到底是否已经触发回收。