DDMS analysize 方法

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

1 內存泄漏的排查方法


Dalvik Debug Monitor Server (DDMS) ADT插件的一部分,其中有兩項功能可用於內存檢查 :


·    heap 查看堆的分配情況


·    allocation tracker跟蹤內存分配情況


DDMS 這兩項功能有助於找到內存泄漏的操作行爲。


Eclipse Memory Analysis Tools (MAT) 是一個分析 Java堆數據的專業工具,用它可以定位內存泄漏的原因。


工具地址 : https://www.eclipse.org/mat/



1.1 觀察 Heap



·        運行程序,然後進入 DDMS管理界面,如下:


 


PS : 點擊工具欄上的  來更新統計信息


點擊右側的 Cause GC 按鈕或工具欄上的  即可查看當前的堆情況,如下: 




主要關注兩項數據:


o    Heap Size 堆的大小,當資源增加,當前堆的空餘空間不夠時,系統會增加堆的大小,若超過上限 (例如 64M,視平臺和具體機型而定)則會被殺掉


o    Allocated 堆中已分配的大小,這是應用程序實際佔用的內存大小,資源回收後,此項數據會變小


·        查看操作前後的堆數據,看是否有內存泄漏 
對單一操作(比如添加頁,刪除頁)進行反覆操作,如果堆的大小一直增加,則有內存泄漏的隱患。



1.2 利用MAT分析內存堆



DDMS 可以將當前的內存 Dump成一個 hprof格式的文件,MAT讀取這個文件後會給出方便閱讀的信息,配合它的查找,對比功能,就可以定位內存泄漏的原因。


·        獲取 hprof文件 
點擊工具欄上的  按鈕,將內存信息保存成文件。 如果是用 MAT Eclipse 插件獲取的 Dump文件,則不需要經過轉換,Adt會自動進行轉換然後打開。


·        轉換 hprof文件 
DDMS Dump
出的文件要經過轉換才能被 MAT識別,Android SDK提供了這個工具 hprof-conv (位於 sdk/tools)


·    ./hprof-conv xxx-a.hprof xxx-b.hprof


·         MAT打開轉換後的 hprof文件 





1.3  Histogram 查詢



用的最多的功能是 Histogram,點擊 Actions下的 Histogram項將得到 Histogram結果




它按類名將所有的實例對象列出來,可以點擊表頭進行排序,在表的第一行可以輸入正則表達式來匹配結果 :




在某一項上右鍵打開菜單選擇 list objects ->with incoming refs 將列出該類的實例:




它展示了對象間的引用關係,比如展開後的第一個子項表示這個 HomePage(0x420ca5b0) HomePageContainer(0x420c9e40)中的 mHomePage屬性所引用.


快速找出某個實例沒被釋放的原因,可以右健 Path to GC Roots-->exclue all phantom/weak/soft etc. reference :




得到的結果是:




從表中可以看出 PreferenceManager -> … ->HomePage這條線路就引用着這個 HomePage實例。用這個方法可以快速找到某個對象的 GC Root,一個存在 GC Root的對象是不會被 GC回收掉的.



1.4  Histogram 對比



爲查找內存泄漏,通常需要兩個 Dump結果作對比,打開 Navigator History面板,將兩個表的 Histogram結果都添加到 Compare Basket中去 :




添加好後,打開 Compare Basket面板,得到結果:




點擊右上角的 ! 按鈕,將得到比對結果:




注意,上面這個對比結果不利於查找差異,可以調整對比選項




再把對比的結果排序,就可得到直觀的對比結果:




也可以對比兩個對象集合,方法與此類似,都是將兩個 Dump結果中的對象集合添加到Compare Basket中去對比。找出差異後用 Histogram查詢的方法找出 GC Root,定位到具體的某個對象上。



1.5  例子



舉例一個典型的分析內存泄漏的過程:


1.  使用 Heap查看當前堆大小爲 23.00M


2.  添加一個頁後堆大小變爲 23.40M


3.  將添加的一個頁刪除,堆大小爲 23.40M


4.  多次操作,結果仍相似,說明添加/刪除頁存在內存泄漏 (也應注意排除其它因素的影響)


5.  Dump 出操作前後的 hprof 文件 (1.hprof,2.hprof),用 mat打開,並得到 histgram結果


6.  使用 HomePage字段過濾 histgram結果,並列出該類的對象實例列表,看到兩個表中的對象集合大小不同,操作後比操作前多出一個 HomePage,說明確實存在泄漏


7.  將兩個列表進行對比,找出多出的一個對象,用查找 GC Root的方法找出是誰串起了這條引用線路,定位結束


PS :


·        很多時候堆增大是 Bitmap引起的,Bitmap Histogram中的類型是 byte [],對比兩個 Histogram中的 byte[]對象就可以找出哪些 Bitmap有差異


·        多使用排序功能,對找出差異很有用



2 內存泄漏的原因分析



總結出來只有一條: 存在無效的引用! 
良好的模塊設計以及合理使用設計模式有助於解決此問題。



3 Tips



·    使用 android:largeHeap="true"標記 (API Level >= 11) 
AndroidManifest.xml中的 Application節點中聲明即可分配到更大的堆內存, android:largeHeap標記在 Android系統應用中也有廣泛的應用 ,比如 Launcher, Browser這些內存大戶上均有使用.



4 參考



·    DDMS 官方教程 http://developer.android.com/tools/debugging/ddms.html


·    MAT 下載 http://www.eclipse.org/mat/downloads.php


·    MAT 使用 http://android-developers.blogspot.tw/2011/03/memory-analysis-for-android.html


 同事起草,整理分享,可以轉載收錄。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章