LeakCanary原理

1. LeakCanary是幫忙我們查詢內存泄露的,只需要簡單的繼承,當發生內存泄露時,就會在手機的桌面上生成內存泄露的文件,.hprof 文件。

打開文件大概如下圖,幫助我們分析內存泄露的原因

2. 原理

通過registerActivityLifecycleCallbacks 檢測Activity的生命週期。 在Activity執行onDestroy時,開始檢測。

檢測之前,介紹一下LeakCanary的一個核心的類。

KeyedWeakReference。它是弱引用的子類。我們看一下它的構造函數

參數Object refernce:  是這個弱引用指向的對象。

參數ReferenceQueue<Object>  referenceQueue:   這個是是一個隊列,如果弱引用指向的對象被GC回收,那麼對象就會被添加到此隊列中。 所以我們可以判斷,如果一個對象出現在了referenceQueue中,我們就可以認爲它已經被GC回收,不存在內存泄露。

 

回到在Activity執行onDestroy時,開始檢測。

//生成一個隨機的Key,和Activity對應

String key = UUID.randomUUID().toString();

//把這個key添加到retainedKeys,retainedKeys是還沒有被GC回收的activity的Key的集合

this.retainedKeys.add(key);

// 生成一個弱引用KeyedWeakReference指向我的要destory的activity

//watchedReference 是要destory的activity. 

//傳入queue,用來收集稍後被GC回收的activity對象

final KeyedWeakReference reference = new KeyedWeakReference(watchedReference, key, referenceName, this.queue);

// 向handler發送一個ensureGone操作,注意這是一個Idle類型的只有handler空閒纔會執行,所以不會阻塞正常的操作。

this.watchExecutor.execute(new Runnable() {
    public void run() {
        RefWatcher.this.ensureGone(reference, watchStartNanoTime);
    }
});

***************準備工作做好了,等待handler空閒執行ensureGone方法******************

ensureGone的時候,handler已經忙完了,正常來說onDestory已經都執行結束了,我們的Activity正常來說應該被回收了。

從queue中不斷poll出對象,獲取到對應的Key, 並從retainedKeys刪除對應的key.

因爲queue中的對象被GC回收,所以把他從retainedKeys除去

queue爲null後,判斷ensureGone傳入的reference的key是否已經不存在在retainedKeys中了。

如果不存在證明確實被GC回收。不用管了,這個activity沒發生內存泄露

如果還在,那麼 this.gcTrigger.runGc(); 再執行一次GC操作。在從queue中不斷poll出對象,獲取到對應的Key, 並從retainedKeys刪除對應的key.....判斷ensureGone傳入的reference的key是否已經不存在在retainedKeys中了。

如果retainedKeys找不到對應的key,說明確實被GC回收。不用管了,這個activity沒發生內存泄露

如果還存在在retainedKeys說明Activity發生內存泄露。

File heapDumpFile = this.heapDumper.dumpHeap(); dump出內存文件。由於這個過程比較耗時,啓動 HeapAnalyzerService ,HeapAnalyzerService通過調用HeapAnalyzer的checkForLeak方法進行內存分析。最終用到

eclipse mat 進行分析,打印內存泄露的路徑
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章