美文网首页
LeakCanary源码解读

LeakCanary源码解读

作者: android_hcf | 来源:发表于2017-06-14 15:22 被阅读86次

版权声明:本文为原创文章,未经允许不得转载。

LeakCanary是一个安卓的性能统计工具,想必大家都有使用,工具出自大名鼎鼎的Jake Wharton大神,截止目前为止其在GitHub的star数目已达到15.4k,可见其受到的欢迎程度,下面我将通过UML类图以及流程图,最后配上部分源码对源码进行解析。

一、LeakCanary流程图

LeakCanary的代码风格主要使用的是Builder建造者模式,其主要的思想也就是监听Activity的销毁,然后进行性能统计,目前其仅支持SDK14版本及以上,不过已覆盖绝大多数手机。其流程图很简单,如下:

LeakCanary流程图.png

如图可见,直到执行buildAndInstall()之前都是搜集所需属性,然后通过buildAndInstall()方法执行安卓统计。这里仅仅是让大家有个整体的执行流程的了解。

二、LeakCanary类图

LeakCanary类图.png

如开头所说,LeakCanary的代码风格以Builder建造者为主,在该类图中可见建造者为AndroidRefWatcherBuilder,其继承于父类RefWatcherBuilder。

三、LeakCanary源码执行流程

AndroidRefWatcherBuilder作为整个库的核心建造者,其属性如下:

private ExcludedRefs excludedRefs;
private Listener heapDumpListener;
private DebuggerControl debuggerControl;
private HeapDumper heapDumper;
private WatchExecutor watchExecutor;
private GcTrigger gcTrigger;

下面再来看下LeakCanary执行的入口方法install源码:

public staticRefWatcher install(Application application) {
   return((AndroidRefWatcherBuilder)refWatcher(application)
       .listenerServiceClass(DisplayLeakService.class)
       .excludedRefs(AndroidExcludedRefs.createAppDefaults().build()))
       .buildAndInstall();
}

继续跟进listenerServiceClass方法:

public AndroidRefWatcherBuilder listenerServiceClass(Class listenerServiceClass) {
   return (AndroidRefWatcherBuilder)this.heapDumpListener(new ServiceHeapDumpListener(this.context, listenerServiceClass));
}

通过该两种方法发现,AndroidRefWatcherBuilder默认已实现了heapDumpListener和excludedRefs。
最后再来看看AndroidRefWatcherBuilder的buildAndInstall方法,也就是入口install方法最终执行的方法:

public RefWatcher buildAndInstall() {
   RefWatcher refWatcher = this.build();
   if(refWatcher != RefWatcher.DISABLED) {
       LeakCanary.enableDisplayLeakActivity(this.context);
       ActivityRefWatcher.installOnIcsPlus((Application)this.context,refWatcher);
   }
   return refWatcher;
}

该方法主要做了3件事情:build;注册DisplayLeakActivity,用于显示性能统计结果;以及安装LeakCanary。
继续跟进installOnlcsPlus,最终执行了如下方法:

private final ActivityLifecycleCallbacks lifecycleCallbacks = new ActivityLifecycleCallbacks() {
    ......
    public void onActivityDestroyed(Activity activity) {
        ActivityRefWatcher.this.onActivityDestroyed(activity);
    }
};
public void watchActivities() {
    this.stopWatchingActivities();
    this.application.registerActivityLifecycleCallbacks(this.lifecycleCallbacks);
}

由此可以得出一个结论,LeakCanary性能统计的原理就是通过监听每个Activity的销毁,在销毁过程中统计该页面的性能情况。
我们再来继续跟进ActivityRefWatcher.this.onActivityDestroyed(activity)方法,最终执行了如下代码片段:

Result ensureGone(KeyedWeakReference reference, long watchStartNanoTime) {
    ......
    this.gcTrigger.runGc();
    ......
    File heapDumpFile =this.heapDumper.dumpHeap();
    ......
    this.heapdumpListener.analyze(newHeapDump(heapDumpFile,reference.key,reference.name, this.excludedRefs,watchDurationMs,gcDurationMs,heapDumpDurationMs));
    return Result.DONE;
}

该方法主要做了两件事情:
1,生成性能统计文件.hprof,关键代码如下:

Debug.dumpHprofData(heapDumpFile.getAbsolutePath());

2,分析文件。分析文件的过程在service服务当中,该服务正是入口方法放进去的DisplayLeakService,最终将生成的.hprof文件通过通知的形式呈现出来:

protected final void onHeapAnalyzed(HeapDump heapDump, AnalysisResult result) {
    ......
    LeakCanaryInternals.showNotification(this, contentTitle, contentText, pendingIntent, notificationId1);
}

其中AnalysisResult是.hprof的分析结果。

讲到这里,可能某些读者仍有些疑问,到底.hprof文件是如何解析成信息的?源码的处理的关键语句是这样的:

AnalysisResult result = heapAnalyzer.checkForLeak(heapDump.heapDumpFile, heapDump.referenceKey);

没错,性能统计文件转化为信息的代码正是checkForLeak,具体实现逻辑在HeapAnalyzer里面:

public AnalysisResult checkForLeak(File heapDumpFile, String referenceKey) {
    ......
    MemoryMappedFileBuffer e = new MemoryMappedFileBuffer(heapDumpFile);
    HprofParser parser = new HprofParser(e);
    Snapshot snapshot = parser.parse();
    this.deduplicateGcRoots(snapshot);
    Instance leakingRef = this.findLeakingReference(referenceKey, snapshot);
    return leakingRef == null ? AnalysisResult.noLeak(this.since(analysisStartNanoTime)) : this.findLeakTrace(analysisStartNanoTime, snapshot, leakingRef);
}

这里,执行转化的方法为HprofParser的parse方法,然后再将转化的信息封装成AnalysisResult对象,其中HprofParser也是自定义的类,里面有一定的篇幅解析.hprof文件,感兴趣的同学可以继续深入研究。

至此,整个LeakCanary的建造以及执行流程已梳理完毕。

相关文章

  • LeakCanary源码解读

    版权声明:本文为原创文章,未经允许不得转载。 LeakCanary是一个安卓的性能统计工具,想必大家都有使用,工具...

  • LeakCanary 2.0源码分析与总结

    本文基于LeakCanary 2.0源码分析LeakCanary - 官方地址LeakCanary - GitHu...

  • LeakCanary源码解析

    开源库路径https://github.com/square/leakcanary 源码结构 leakcanary...

  • LeakCanary 原理分析

    本文主要内容 1、Reference 简介 2、LeakCanary 使用 3、LeakCanary 源码分析 L...

  • LeakCanary原理

    一、源码 LeakCanary内存分析模块,独立进程,包名:leakcanary,保持app进程独立。在Appli...

  • 监测内存泄漏--LeakCanary源码分析

    1 在全局Application类中注册: LeakCanary.install(this);点进去看源码: 源码...

  • LeakCanary源码解析

    LeakCanary源码解析 前言 对于内存泄漏的检测,基于MAT起点较高,所以一般我们都使用LeakCanary...

  • LeakCanary源码解析

    LeakCanary源码解析 内存泄露 今天来讲解一下老生常谈的问题了,内存泄露以及讲解LeakCanary是如果...

  • LeakCanary详解

    应用层的使用和改进: 深入Leakcanary的源码: LeakCanary原理 原理: 正常情况下一个Activ...

  • LeakCanary源码笔记

    LeakCanary 由Square开源的一款轻量级第三方内存泄漏检测工具为什么需要LeakCanary框架:性能...

网友评论

      本文标题:LeakCanary源码解读

      本文链接:https://www.haomeiwen.com/subject/kiusqxtx.html