如果使用DDMS確實發現了我們程序中存在內存泄露,那如何定位到具體出現問題的代碼片段,最終找到問題所在呢?如果從頭到尾分析代碼邏輯,那肯定會把人逼瘋,特別是在維護別人寫的代碼的時候。這里介紹一個極好的內存分析工具Memory Analyzer Tool(MAT)。
-
在Eclipse中安裝和使用MAT步驟
-
Eclipse安裝Allocation tracker插件
MAT是一個Eclipse插件,同時也有單獨的RCP客戶端。
如果安裝Eclipse插件(更方便使用,本文介紹的是使用Eclipse插件)。使用http://download.eclipse.org/mat/1.2/update-site/進行安裝。
-
生成.hprof文件
打開Eclipse,切換到DDMS透視圖,同時確認Devices、Heap和logat視圖已經打開。
將手機設備連接到電腦,並確保使用“USB調試“模式鏈接,
鏈接成功后在Devices視圖中就會看到設備的序列號,和設備正在運行的部分進程。
選中想要分析的應用進程,在Devices視圖上方的一行圖標按鈕中,同時選中“Update Heap”和“Dump HPROF file”按鈕。
彈出Getting Started向導對話框,選中Leak Suspects Report,點擊Finish按鈕。
-
使用MAT打開並導入.hprof文件
Eclipse自動跳轉到Memory Analysize透視圖,並打開default_report窗口。
該窗口列出了,可能有問題的代碼片段。點擊Details可以查看相關的詳情。
在Shortest Paths To the Accumulation Point的列表中,我們可以追溯到問題代碼的類樹的結構,並找到自己代碼中的類。
在列表中,有兩列Shallow Heap和Retained Heap。Shallow Heap指的是所有的實例的內存總和。Retained Heap指的是所有類實例被分配的內存總和,里面包括它們所有引用的對象。
在Accumulated Objects列表中,我們可以看見創建的大量的對象。
在Accumulated Objects by Class列表中,我們能看見創建大量對象相關的類。
-
使用MAT視圖工具分析內存
點擊Histogrm按鈕,顯示了Histogrm視圖,它顯示了一個可以排序的類實例的列表。並可以根據自己的意願,修改排序。
右擊某一行,選擇ListObjects>with incoming references,它會生成一個heap上的所有該對象數組的列表,我們可以按照Shallow Heap的使用情況來排序。
選擇一個較大的對象,右擊,選擇Path to GCRoot->exclude weak/soft reference。
被JVM持有的對象,如當前運行的線程對象,被systemclass loader加載的對象稱為GC Roots。從一個對象到GC Roots的引用鏈被稱為Path to GC Roots,
通過分析Path to GC Root可以找出Java的內存泄露問題,當程序不在訪問該對象時,仍然存在到該對象的引用路徑。
MAT不會明確的告訴我們這就是內存泄露,因為它也不知道這個東西是不是程序需要的,只有程序員知道。
點擊Domanitor_tree按鈕,彈出新的窗口,列出了對中最大的對象,第二層級節點標識當被第一層級的節點所引用到的對象,當第一層級的節點被回收時,這些對象也將會回收。
這個工具可以幫我們定位對象間的引用情況,垃圾回收時候的引用關系。