天天看點

Android 記憶體監測工具 DDMS --> Heap

用 Heap監測應用程序使用記憶體情況的步驟如下:

1. 啟動eclipse後,切換到DDMS透視圖,并确認Devices視圖、Heap視圖都是打開的;

2. 将手機通過USB連結至電腦,連結時需要确認手機是處于“USB調試”模式,而不是作為“Mass Storage”;

3. 連結成功後,在DDMS的Devices視圖中将會顯示手機裝置的序列号,以及裝置中正在運作的部分程序資訊;

4. 點選選中想要監測的程序,比如system_process程序;

5. 點選選中Devices視圖界面中最上方一排圖示中的“Update Heap”圖示;

6. 點選Heap視圖中的“Cause GC”按鈕;

7. 此時在Heap視圖中就會看到目前選中的程序的記憶體使用量的詳細情況。

說明:

a) 點選“Cause GC”按鈕相當于向虛拟機請求了一次gc操作;

b) 當記憶體使用資訊第一次顯示以後,無須再不斷的點選“Cause GC”,Heap視圖界面會定時重新整理,在對應用的不斷的操作過程中就可以看到記憶體使用的變化;

c) 記憶體使用資訊的各項參數根據名稱即可知道其意思,在此不再贅述。

  如何才能知道我們的程式是否有記憶體洩漏的可能性呢。這裡需要注意一個值:Heap視圖中部有一個Type叫做data object,即資料對象,也就是我們的程式中大量存在的類類型的對象。在data object一行中有一列是“Total Size”,其值就是目前程序中所有Java資料對象的記憶體總量,一般情況下,這個值的大小決定了是否會有記憶體洩漏。可以這樣判斷:

a) 不斷的操作目前應用,同時注意觀察data object的Total Size值;

b) 正常情況下Total Size值都會穩定在一個有限的範圍内,也就是說由于程式中的的代碼良好,沒有造成對象不被垃圾回收的情況,是以說雖然我們不斷的操作會不斷的生成很多對 象,而在虛拟機不斷的進行GC的過程中,這些對象都被回收了,記憶體占用量會會落到一個穩定的水準;

c) 反之如果代碼中存在沒有釋放對象引用的情況,則data object的Total Size值在每次GC後不會有明顯的回落,随着操作次數的增多Total Size的值會越來越大,

  直到到達一個上限後導緻程序被kill掉。

d) 此處已system_process程序為例,在我的測試環境中system_process程序所占用的記憶體的data object的Total Size正常情況下會穩定在2.2~2.8之間,而當其值超過3.55後程序就會被kill。

來自: http://apps.hi.baidu.com/share/detail/32190286

在DDMS裡檢查heap的使用情況

Dalvik Debug Monitor Server(DDMS)是主要的Android調試工具之一,也是ADT Eclipse plug-in 的一部分,獨立的程式版本也可以在Android SDK的根目錄下的tools/下面找到。關于DDMS更多的資訊,請參考使用DDMS 。

我們來使用DDMS檢查這個應用的heap使用情況。你可以使用下面的兩種方法啟動DDMS:

  • from Eclipse: click Window > Open Perspective > Other... > DDMS
  • or from the command line: run 

    ddms

     (or 

    ./ddms

     on Mac/Linux) in the 

    tools/

     directory
Android 記憶體監測工具 DDMS --> Heap

在左邊的面闆選擇程序com.example.android.hcgallery,然後在 工具條上邊點選Show heap updates按鈕。這個時候切換到DDMS的VM Heap分頁。它會顯示每次gc後heap記憶體的一些基本資料。要看第一次gc後的資料内容,點選Cause GC按鈕:

Android 記憶體監測工具 DDMS --> Heap

我們可以看到現在的值(Allocated列)是有一些超過8MB。現在滑動相片,這時看到 資料在增大。因為隻有僅僅13個相片在程式裡邊,是以洩露的記憶體隻有這麼大。在某種程度上來說,這時最壞的一種記憶體洩露,因為我們沒法得到 OutOfMemoryError來提醒我們說現在記憶體溢出了。

生成heap dump

我們現在使用heap dump來追蹤這個問題。點選DDMS工具條上面的Dump HPROF檔案按鈕,選擇檔案存儲位置,然後在運作hprof-conv。在這個例子裡我們使用獨立的MAT版本(版本1.0.1),從MAT站點下載下傳 。

如果你使用ADT(它包含DDMS的插件)同時也在eclipse裡面安裝了MAT,點選“dump HPROF”按鈕将會自動地做轉換(用hprof-conv)同時會在eclipse裡面打開轉換後的hprof檔案(它其實用MAT打開)。

用MAT分析heap dumps

啟動MAT然後加載剛才我們生成的HPROF檔案。MAT是一個強大的工具,講述它所有的特性超出了本文的範圍,是以我隻想示範一種你可以用來檢測 洩露的方法:直方圖(Histogram)視圖。它顯示了一個可以排序的類執行個體的清單,内容包括:shallow heap(所有執行個體的記憶體使用總和),或者retained heap(所有類執行個體被配置設定的記憶體總和,裡面也包括他們所有引用的對象)。

Android 記憶體監測工具 DDMS --> Heap

如果我們按照shallow heap排序,我們可以看到byte[]執行個體在頂端。自從Android3.0(Honeycomb),Bitmap的像素資料被存儲在byte數組裡 (之前是被存儲在Dalvik的heap裡),是以基于這個對象的大小來判斷,不用說它一定是我們洩露掉的bitmap。

右擊byte[]類然後選擇List Objects > with incoming references。它會生成一個heap上的所有byte數組的清單,在清單裡,我們可以按照Shallow Heap的使用情況來排序。

選擇并展開一個比較大的對象,它将展示從根到這個對象的路徑--就是一條保證對象有效的鍊條。注意看,這個就是我們的bitmap緩存!

Android 記憶體監測工具 DDMS --> Heap

MAT不會明确告訴我們這就是洩露,因為它也不知道這個東西是不是程式還需要的,隻有程式員知道。在這個案例裡面,緩存使用的大量的記憶體會影響到後面的應用程式,是以我們可以考慮限制緩存的大小。

使用MAT比較heap dumps

調試記憶體洩露時,有時候适時比較2個地方的heap狀态是很有用的。這時你就需要生成2個單獨的HPROF檔案(不要忘了轉換格式)。下面是一些關于如何在MAT裡比較2個heap dumps的内容(有一點複雜):

  1. 第一個HPROF 檔案(using File > Open Heap Dump ).
  2. 打開 Histogram view.
  3. 在Navigation History view裡 (如果看不到就從Window > Navigation History找 ), 右擊histogram 然後選擇Add to Compare Basket .
  4. 打開第二個HPROF 檔案然後重做步驟2和3.
  5. 切換到Compare Basket view, 然後點選Compare the Results (視圖右上角的紅色"!"圖示)。

總結

這本篇文章裡面,我展示了Allocation Tracker和heap dumps是如何給你一種對程式記憶體使用的感性認識。我也展示了Eclipse Memory Analyzer(MAT)可以幫助追逐我們程式裡面的記憶體洩露問題。MAT是一個強大的工具,我也僅僅觸碰了一些皮毛,如果你想學習更多内容,我建議讀 一些下面的文章:

  • Memory Analyzer News : Eclipse MAT project的官方部落格。
  • Markus Kohler的Java Performance blog有很多有用的文章, 包括 Analysing the Memory Usage of Android Applications with the Eclipse Memory Analyzer and 10 Useful Tips for the Eclipse Memory Analyzer .

來自: http://dev.10086.cn/blog/?uid-13136-action-viewspace-itemid-9580

繼續閱讀