版權(quán)聲明:本文為原創(chuàng)文章续语,未經(jīng)允許不得轉(zhuǎn)載弃酌。
LeakCanary是一個(gè)安卓的性能統(tǒng)計(jì)工具,想必大家都有使用锦积,工具出自大名鼎鼎的Jake Wharton大神,截止目前為止其在GitHub的star數(shù)目已達(dá)到15.4k歉嗓,可見其受到的歡迎程度丰介,下面我將通過UML類圖以及流程圖,最后配上部分源碼對(duì)源碼進(jìn)行解析鉴分。
一哮幢、LeakCanary流程圖
LeakCanary的代碼風(fēng)格主要使用的是Builder建造者模式,其主要的思想也就是監(jiān)聽Activity的銷毀志珍,然后進(jìn)行性能統(tǒng)計(jì)橙垢,目前其僅支持SDK14版本及以上,不過已覆蓋絕大多數(shù)手機(jī)伦糯。其流程圖很簡(jiǎn)單柜某,如下:
如圖可見,直到執(zhí)行buildAndInstall()之前都是搜集所需屬性敛纲,然后通過buildAndInstall()方法執(zhí)行安卓統(tǒng)計(jì)喂击。這里僅僅是讓大家有個(gè)整體的執(zhí)行流程的了解。
二载慈、LeakCanary類圖
如開頭所說惭等,LeakCanary的代碼風(fēng)格以Builder建造者為主,在該類圖中可見建造者為AndroidRefWatcherBuilder办铡,其繼承于父類RefWatcherBuilder辞做。
三琳要、LeakCanary源碼執(zhí)行流程
AndroidRefWatcherBuilder作為整個(gè)庫(kù)的核心建造者,其屬性如下:
private ExcludedRefs excludedRefs;
private Listener heapDumpListener;
private DebuggerControl debuggerControl;
private HeapDumper heapDumper;
private WatchExecutor watchExecutor;
private GcTrigger gcTrigger;
下面再來看下LeakCanary執(zhí)行的入口方法install源碼:
public staticRefWatcher install(Application application) {
return((AndroidRefWatcherBuilder)refWatcher(application)
.listenerServiceClass(DisplayLeakService.class)
.excludedRefs(AndroidExcludedRefs.createAppDefaults().build()))
.buildAndInstall();
}
繼續(xù)跟進(jìn)listenerServiceClass方法:
public AndroidRefWatcherBuilder listenerServiceClass(Class listenerServiceClass) {
return (AndroidRefWatcherBuilder)this.heapDumpListener(new ServiceHeapDumpListener(this.context, listenerServiceClass));
}
通過該兩種方法發(fā)現(xiàn)秤茅,AndroidRefWatcherBuilder默認(rèn)已實(shí)現(xiàn)了heapDumpListener和excludedRefs稚补。
最后再來看看AndroidRefWatcherBuilder的buildAndInstall方法,也就是入口install方法最終執(zhí)行的方法:
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框喳;注冊(cè)DisplayLeakActivity课幕,用于顯示性能統(tǒng)計(jì)結(jié)果;以及安裝LeakCanary五垮。
繼續(xù)跟進(jìn)installOnlcsPlus乍惊,最終執(zhí)行了如下方法:
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);
}
由此可以得出一個(gè)結(jié)論,LeakCanary性能統(tǒng)計(jì)的原理就是通過監(jiān)聽每個(gè)Activity的銷毀放仗,在銷毀過程中統(tǒng)計(jì)該頁面的性能情況润绎。
我們?cè)賮砝^續(xù)跟進(jìn)ActivityRefWatcher.this.onActivityDestroyed(activity)方法,最終執(zhí)行了如下代碼片段:
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诞挨,生成性能統(tǒng)計(jì)文件.hprof莉撇,關(guān)鍵代碼如下:
Debug.dumpHprofData(heapDumpFile.getAbsolutePath());
2,分析文件惶傻。分析文件的過程在service服務(wù)當(dāng)中棍郎,該服務(wù)正是入口方法放進(jìn)去的DisplayLeakService,最終將生成的.hprof文件通過通知的形式呈現(xiàn)出來:
protected final void onHeapAnalyzed(HeapDump heapDump, AnalysisResult result) {
......
LeakCanaryInternals.showNotification(this, contentTitle, contentText, pendingIntent, notificationId1);
}
其中AnalysisResult是.hprof的分析結(jié)果银室。
講到這里涂佃,可能某些讀者仍有些疑問,到底.hprof文件是如何解析成信息的蜈敢?源碼的處理的關(guān)鍵語句是這樣的:
AnalysisResult result = heapAnalyzer.checkForLeak(heapDump.heapDumpFile, heapDump.referenceKey);
沒錯(cuò)巡李,性能統(tǒng)計(jì)文件轉(zhuǎn)化為信息的代碼正是checkForLeak,具體實(shí)現(xiàn)邏輯在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);
}
這里扶认,執(zhí)行轉(zhuǎn)化的方法為HprofParser的parse方法,然后再將轉(zhuǎn)化的信息封裝成AnalysisResult對(duì)象殊橙,其中HprofParser也是自定義的類辐宾,里面有一定的篇幅解析.hprof文件,感興趣的同學(xué)可以繼續(xù)深入研究膨蛮。
至此叠纹,整個(gè)LeakCanary的建造以及執(zhí)行流程已梳理完畢。