LeakCanary源码分析

来源:互联网 发布:数据库测试题 编辑:程序博客网 时间:2024/06/06 20:53

LeakCanary源码分析

LeakCanary是一个Android内存泄露自动分析工具,具有简单易用,结果可读性强,不仅适用于Android开发人员,也适用于测试人员使用。能快速提高软件质量。github地址:https://github.com/square/leakcanary

leakCanary包含3个模块leakcanary-android(leakcanary-android-no-op),leakcanary-watcher和leakcanary-analyzer。

leakcanary-android debug使用。负责启动内存泄露检测,给别的应用提供接口,包括启动和分析结果展示。

leakcanary-android-no-opleakcanary-android一样,一般用在release版本中。

leakcanary-watcher 检测对象是否发生内存泄露,如果发生内存泄露则导出堆信息到本地文件中(*.hprof)

leakcanary-analyzer 从*.hprof文件中分析对象发生内存泄露原因,找出哪些对象强引用者监听对象。并将结果告诉leakcanary-android

一. 流程图

这里写图片描述

二. 时序图

这里写图片描述

三. 重要类分析

1 LeakCanary: 入口类

/**启动对Activity内存泄露监听**/public static RefWatcher install(Application application);/**根据内存泄露分析结果,生成面向人的分析报告**/public static String leakInfo(Context context, HeapDump heapDump, AnalysisResult result,boolean detailed);

2 ActivityRefWatcher:这是一个代理类,主要功能是:注册ActivityLifecycleCallbacks回调,当Activity执行ondestroy()前,启动RefWatcher检测该Activity是否发生内存泄露。

3 RefWatcher:内存泄露检测核心类

/**     * Watches the provided references and checks if it can be GCed. This method is non blocking,     * the check is done on the {@link Executor} this {@link RefWatcher} has been constructed with.     *     * @param referenceName An logical identifier for the watched object.     */    public void watch(Object watchedReference, String referenceName);  /**  *查看reference指向的对象是否发生内存泄露,如果发生泄露则启动HeapDump.dumpHeap()导出heap快照  */  void ensureGone(KeyedWeakReference reference, long watchStartNanoTime);

4 AndroidHeapDumper 实现了接口HeapDumper,导出当前内存快照到文件中。使用了Android自带的Debug类导出内存快照。

/** * 导出内存快照,保存到heapDumpFile文件中 */@Override public File dumpHeap() {    File heapDumpFile = getHeapDumpFile();    boolean fileCreated;    try {      fileCreated = heapDumpFile.createNewFile();    } catch (IOException e) {      cleanup();      CanaryLog.d(e, "Could not check if heap dump file exists");      return NO_DUMP;    }    Debug.dumpHprofData(heapDumpFile.getAbsolutePath());    return heapDumpFile;   }

Debug.dumpHprofData(heapDumpFile.getAbsolutePath());

5 KeyedWeakReference: WeakReference的子类

String key;//用时间戳来唯一标识一个弱引用KeyedWeakReference(Object referent, String key, String name,                       ReferenceQueue<Object> referenceQueue) {        super(checkNotNull(referent, "referent"), checkNotNull(referenceQueue, "referenceQueue"));        this.key = checkNotNull(key, "key");        this.name = checkNotNull(name, "name");    }

构造函数传了一个ReferenceQueue给父类WeakReference。ReferenceQueue的作用是,当被引用的对象被JVM释放的时候会在该队列中生成一条记录(把该对象的弱引用放到该队列中),即:我们通过检查ReferenceQueue中是否存在我们关心的KeyedWeakReference来判断引用的对象是否被成功释放。代码如下:

KeyedWeakReference ref;boolean isLeak;while ((ref = (KeyedWeakReference) queue.poll()) != null) {  retainedKeys.remove(ref.key);  isLeak =  !(retainedKeys.contains(ref.key));}if(retainedKeys.contains(ref.key)){  isLeak = true;}

6 ServiceHeapDumpListener:类存泄露监听器,当检测到发生内存,并且内存快照被导出到文件后,在该监听器中调用内存泄露分析工具。

7 HeapAnalyzerService:内存泄露分析Service,该类继承与IntentService,每个Intent在子线程中处理

8 HeapAnalyzer:类存泄露分析工具类

9 AbstractAnalysisResultService:负责接收内存泄露分析结果的Service

10 AnalysisResult:分析结果Model,结构如下:

/** True if a leak was found in the heap dump. */public final boolean leakFound;/** * True if {@link #leakFound} is true and the only path to the leaking reference is * through excluded references. Usually, that means you can safely ignore this report.* 如果为true,表示该泄露不是应用发生的,可以忽略 */public final boolean excludedLeak;/** * Class name of the object that leaked if {@link #leakFound} is true, null otherwise. * The class name format is the same as what would be returned by {@link Class#getName()}. */public final String className;/** * Shortest path to GC roots for the leaking object if {@link #leakFound} is true, null * otherwise. This can be used as a unique signature for the leak. */public final LeakTrace leakTrace;/** Null unless the analysis failed. */public final Throwable failure;/** * The number of bytes which would be freed if all references to the leaking object were * released. 0 if {@link #leakFound} is false. */public final long retainedHeapSize;/** Total time spent analyzing the heap. */public final long analysisDurationMs;
1 0
原创粉丝点击