android內存泄露調試,Heap,MAT

3、內存監測工具 DDMS --> Heap

    不管怎麼當心,想徹底避免bad code是不可能的,此時就須要一些工具來幫助咱們檢查代碼中是否存在會形成內存泄漏的地方。Android tools中的DDMS就帶有一個很不錯的內存監測工具Heap(這裏我使用eclipse的ADT插件,並以真機爲例,在模擬器中的狀況相似)。用Heap監測應用進程使用內存狀況的步驟以下:php

1. 啓動eclipse後,切換到DDMS透視圖,並確認Devices視圖、Heap視圖都是打開的;html

2. 將手機經過USB連接至電腦,連接時須要確認手機是處於「USB調試」模式,而不是做爲「Mass Storage」;android

3. 連接成功後,在DDMS的Devices視圖中將會顯示手機設備的序列號,以及設備中正在運行的部分進程信息;git

4. 點擊選中想要監測的進程,好比system_process進程;app

5. 點擊選中Devices視圖界面中最上方一排圖標中的「Update Heap」圖標;eclipse

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。

 

    總之,使用DDMS的Heap視圖工具能夠很方便的確認咱們的程序是否存在內存泄漏的可能性。

4、內存分析工具 MAT(Memory Analyzer Tool)

    若是使用DDMS確實發現了咱們的程序中存在內存泄漏,那又如何定位到具體出現問題的代碼片斷,最終找到問題所在呢?若是從頭至尾的分析代碼邏輯,那確定會把人逼瘋,特別是在維護別人寫的代碼的時候。這裏介紹一個極好的內存分析工具 -- Memory Analyzer Tool(MAT)。

    MAT是一個Eclipse插件,同時也有單獨的RCP客戶端。官方下載地址、MAT介紹和詳細的使用教程請參見:www.eclipse.org/mat,在此不進行說明了。另外在MAT安裝後的幫助文檔裏也有完備的使用教程。在此僅舉例說明其使用方法。我本身使用的是MAT的eclipse插件,使用插件要比RCP稍微方便一些。

 

    使用MAT進行內存分析須要幾個步驟,包括:生成.hprof文件、打開MAT並導入.hprof文件、使用MAT的視圖工具分析內存。如下詳細介紹。

(一) 生成.hprof文件

    生成.hprof文件的方法有不少,並且Android的不一樣版本中生成.hprof的方式也稍有差異,我使用的版本的是2.1,各個版本中生成.prof文件的方法請參考:

http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/heap-profiling.html;hb=HEAD。

1. 打開eclipse並切換到DDMS透視圖,同時確認Devices、Heap和logcat視圖已經打開了;

2. 將手機設備連接到電腦,並確保使用「USB 調試」模式連接,而不是「Mass Storage「模式;

3. 連接成功後在Devices視圖中就會看到設備的序列號,和設備中正在運行的部分進程;

4. 點擊選中想要分析的應用的進程,在Devices視圖上方的一行圖標按鈕中,同時選中「Update Heap」和「Dump HPROF file」兩個按鈕;

5. 這是DDMS工具將會自動生成當前選中進程的.hprof文件,並將其進行轉換後存放在sdcard當中,若是你已經安裝了MAT插件,那麼此時MAT將會自動被啓用,並開始對.hprof文件進行分析;

    注意:第4步和第5步可以正常使用前提是咱們須要有sdcard,而且當前進程有向sdcard中寫入的權限(WRITE_EXTERNAL_STORAGE),不然.hprof文件不會被生成,在logcat中會顯示諸如

     ERROR/dalvikvm(8574): hprof: can't open /sdcard/com.xxx.hprof-hptemp: Permission denied. 

    的信息。

   

    若是咱們沒有sdcard,或者當前進程沒有向sdcard寫入的權限(如system_process),那咱們能夠這樣作:

6. 在當前程序中,例如framework中某些代碼中,可使用android.os.Debug中的:

   public static void dumpHprofData(String fileName) throws IOException

   方法,手動的指定.hprof文件的生成位置。例如:

   xxxButton.setOnClickListener(new View.OnClickListener() {

       public void onClick(View view) {

          android.os.Debug.dumpHprofData("/data/temp/myapp.hprof");

          ... ...

       }

   }

    上述代碼意圖是但願在xxxButton被點擊的時候開始抓取內存使用信息,並保存在咱們指定的位置:/data/temp/myapp.hprof,這樣就沒有權限的限制了,並且也無須用sdcard。但要保證/data/temp目錄是存在的。這個路徑能夠本身定義,固然也能夠寫成sdcard當中的某個路徑。

 

(二) 使用MAT導入.hprof文件

1. 若是是eclipse自動生成的.hprof文件,可使用MAT插件直接打開(多是比較新的ADT才支持);

2. 若是eclipse自動生成的.hprof文件不能被MAT直接打開,或者是使用android.os.Debug.dumpHprofData()方法手動生成的.hprof文件,則須要將.hprof文件進行轉換,轉換的方法:

    例如我將.hprof文件拷貝到PC上的/ANDROID_SDK/tools目錄下,並輸入命令hprof-conv xxx.hprof yyy.hprof,其中xxx.hprof爲原始文件,yyy.hprof爲轉換事後的文件。轉換事後的文件自動放在/ANDROID_SDK/tools目錄下。OK,到此爲止,.hprof文件處理完畢,能夠用來分析內存泄露狀況了。

3. 在Eclipse中點擊Windows->Open Perspective->Other->Memory Analyzer,或者打Memory Analyzer Tool的RCP。在MAT中點擊File->Open File,瀏覽並導入剛剛轉換而獲得的.hprof文件。

(三) 使用MAT的視圖工具分析內存

    導入.hprof文件之後,MAT會自動解析並生成報告,點擊Dominator Tree,並按Package分組,選擇本身所定義的Package類點右鍵,在彈出菜單中選擇List objects->With incoming references。這時會列出全部可疑類,右鍵點擊某一項,並選擇Path to GC Roots -> exclude weak/soft references,會進一步篩選出跟程序相關的全部有內存泄露的類。據此,能夠追蹤到代碼中的某一個產生泄露的類。

    MAT的界面以下圖所示。

 

 

    具體的分析方法在此不作說明了,由於在MAT的官方網站和客戶端的幫助文檔中有十分詳盡的介紹。

    瞭解MAT中各個視圖的做用很重要,例如www.eclipse.org/mat/about/screenshots.php中介紹的。

  

    總之使用MAT分析內存查找內存泄漏的根本思路,就是找到哪一個類的對象的引用沒有被釋放,找到沒有被釋放的緣由,也就能夠很容易定位代碼中的哪些片斷的邏輯有問題了。

相關文章
相關標籤/搜索