1. 程式人生 > >Eclipse MAT 記憶體分析工具

Eclipse MAT 記憶體分析工具

記錄下andorid開發中 Eclipse下MATMemory Analysis Tools工具使用過程

參考:http://www.blogjava.net/rosen/archive/2010/06/13/323522.html

http://blog.csdn.net/aaa2832/article/details/19419679

        首先實際情況是 Demo中選擇介面,進入FragmentActivity,利用Fragement建立大量(24個)webview,退出fragmentActivity之後,heapsize不斷增加,利用ddms工具中檢視heapsize,從30M增加到60m不等。

一、利用eclipse DDMS中heap工具檢視heap

(1)選擇ddms檢視

(2)選擇虛擬機器中應用程式的程序,選擇紅色標記①處更新heap(updata heap),然後點選紅色標記③處即可顯示heap情況。其中紅色標記②是儲存記憶體快照(.hprof檔案)按鈕,下文將用到。

幾個引數意義:HeapSize:heap大小

                         Allocated:已分配大小

   Free:空閒空間大小

                        上圖中下面是每種資料型別的詳細資訊。 需要注意的是,其中因為本例中存在一些圖片,因此1-byte array型別的總大小(TotalSize)比較大。

在實際分析中可以參考這些資訊進行初步分析(對我來說實現情況中並不好用,可能還圖樣。。。。)

(二)eclipse MAT工具安裝

百度 eclipse線上安裝MAT工具即可。具體的,eclipse ->help->install new software...在對話方塊中選擇add(④),然後輸入name(⑤隨意,你自己命的名)和location(⑥mat線上安裝地址目前是http://download.eclipse.org/mat/1.5/update-site/),然後選擇OK。在Work With(7)中選擇剛才add的,下面框中就會出現MAT更新的資訊(8)。選擇後一路next即可。因為需要上外網,所以比較擔心網速(google android後遺症),後來發現安裝MAT其實挺快的。


安裝完後右上角會出現MAT檢視按鈕。如果木有的話可以選擇eclipse->windows->open perspectivew->other 中選擇即可出現。

(三)MAT工具的使用

在開發時,一般可以在程式剛執行時獲取一次快照,然後執行一段時間後,獲取一次記憶體快照,然後比較分析哪些類可能存在記憶體洩露以及記憶體洩露的GC引用路徑。注意區分強引用,軟引用,弱引用和虛引用。

本例的框架是 mainActivity有一個button,可以開啟一個FragmentActivity,在fragmentActivity中一次建立24個webView物件。先開啟一次fragmentActivity,在DDMS中點選獲取記憶體快照A,然後back之後再開啟一次fragmentActivity,獲取記憶體快照B。點選獲取後Eclipse會自動分析,按照預設選項開啟即可。

3.1先熟悉下MAT的介面。

(1)預設開啟的是記憶體分析報告,是第一個洩露疑點資訊。本例中剛開始獲取的記憶體快照A以及快照B中android.content.res.Resources類和android.graphics.NinePatch類佔用較多記憶體,分別是疑點1(problem suspect 1)和疑點2。但是在快照A和快照B中這兩部分變化並不大,因此這裡並不是這兩個問題(如兩個快照都有     )。

快照A


快照B


點選按鈕,可以開啟洩露疑點的詳細資訊。details資訊分別列出了各個類積累的物件()。點選className,即下圖中byte[],有一些選項,其中listObject->with incoming reference檢視該類的例項物件,並可以檢視那些物件擁有這些物件。listObject->with outgoing reference檢視該類例項物件並檢視這些物件持有哪些物件的引用。另外Path to GCroot可以檢視到GCroot的引用路徑。


在該頁面最下方有,說明了可能存在的一些線索。最後還有,可以連線到目錄。點開目錄,發現除了剛才的Leaks頁面,還有頁面,記錄了該記憶體快照的一些資訊,可以都點開開啟看一下。

(2)除了default report 頁面,還有其他常用的頁面。比如開啟直方圖工具。該工具列出了所有的類以及其物件數量和shallow heap和retained heap。(具體的含義參考http://www.blogjava.net/rosen/archive/2010/05/21/321575.html)。同時在類列表最上方還支援正則表示式。

3.2 利用MAT進行記憶體快照的對比

首先對比這兩個快照。

開啟直方圖後 ,該直方圖將會新增到該快照的瀏覽歷史中。選擇標記1中的瀏覽歷史,右擊直方圖,選擇add to compare basket,這樣就將該直方圖加入對比欄中(跟zol手機電腦對比差不多。。。)。對快照B進行同樣的操作。然後點開標記2對比欄,選著兩個直方圖,右鍵compare tables進行對比。

對於開啟的對比介面,選擇中的選擇different顯示,既可以看到兩次快照中類的物件的差別。因為每次開啟會建立24個WebView,如果存在記憶體洩露,物件在記憶體中未銷燬,一次應該增加24個物件。那麼因此我選擇兩次快照中增加24個物件的類。發現大部分是webView核心相關。

對比結果並篩選


3.3  利用MAT進行path to GCRoot 路徑分析

我們以com.android.org.chromium.android_webview.AwContentsClientCallbackHelper作為切入點,進行path to GC root。對於這個類類,在兩個記憶體快照的直方圖中利用正則表示式都找到它,然後選擇listObject->with incomeing reference,列出所有物件。在第一個快照中存在24個物件,在第二個快照中存在48個物件。選擇兩個快照中都存在的物件,然後分別右鍵 path to GC root-> exclude all phantom/weak/soft ect. reference,選擇通過強引用到GCroot的路徑。

快照A


快照B 


我們發現對於該物件(@0x43cc1840),在快照A中存在強引用到GCroot,而在快照B中並不存在通過強引用到GC root的路徑。那麼為什麼它依然存在記憶體中呢?因為其可能通過軟引用弱引用或虛引用存在。

同理,我們分析它的軟引用。

右鍵該物件,選擇path to GCroot->exclude all phantom/weak reference即可。我們只分析快照B的結果。

快照B


由上圖可以看出從該物件到GCroot的一條路徑。最終Path到Native stack上的物件中。

具體為什麼存在這一條軟引用呢?原來是由於輸入法相關的原因(inputMethod)。具體的結果由於對底層不夠了解還分析不出來。。。。

注:本文中由於不存在強引用到GC Root,因此不存在記憶體洩露。對於軟引用,當heap區中記憶體夠用時將會一直存在,在記憶體不夠用時會觸發對該軟引用的GC。因此不斷的開啟關閉demo FragmentActivity,heap區會一直增加,最後heap區達到最大size時將會觸發GC。

本文分析完畢。

本人也是菜鳥一枚,第一次寫正兒八經的原創部落格,經驗不足,如果有錯誤或表述歧義的地方望指出。。