天天看點

Android中記憶體洩露代碼優化及檢測

  記憶體洩漏指由于疏忽或錯誤造成程式未能釋放已經不再使用的記憶體的情況。記憶體洩漏并非指記憶體在實體上的消失,而是應用程式配置設定某段記憶體後,由于設計錯誤,導緻在釋放該段記憶體之前就失去了對該段記憶體的控制,進而造成了記憶體的浪費。

        正如下文所說,記憶體洩漏與許多其他問題有着相似的症狀,并且通常情況下隻能由那些可以獲得程式源代碼的程式員才可以分析出來。然而,有不少人習慣于把任何不需要的記憶體使用的增加描述為記憶體洩漏,即使嚴格意義上來說這是不準确的。

一、記憶體洩露

        記憶體洩漏會因為減少可用記憶體的數量進而降低計算機的性能。最終,在最糟糕的情況下,過多的可用記憶體被配置設定掉導緻全部或部分裝置停止正常工作,或者應用程式崩潰。

        記憶體洩漏可能不嚴重,甚至能夠被正常的手段檢測出來。在現代作業系統中,一個應用程式使用的正常記憶體在程式終止時被釋放。這表示一個短暫運作的應用程式中的記憶體洩漏不會導緻嚴重後果。

        在以下情況,記憶體洩漏導緻較嚴重的後果:

        1)程式運作後置之不理,并且随着時間的流失消耗越來越多的記憶體(比如伺服器上的背景任務,尤其是嵌入式系統中的背景任務,這些任務可能被運作後很多年内都置之不理);

        2)新的記憶體被頻繁地配置設定,比如當顯示電腦遊戲或動畫視訊畫面時;

        3)程式能夠請求未被釋放的記憶體(比如共享記憶體),甚至是在程式終止的時候;

        4)洩漏在作業系統内部發生;

        5)洩漏在系統關鍵驅動中發生;

        6)記憶體非常有限,比如在嵌入式系統或便攜裝置中;

        7)當運作于一個終止時記憶體并不自動釋放的作業系統(比如amigaos)之上,而且一旦丢失隻能通過重新開機來恢複。

二、記憶體洩漏檢測工具

        當一個java對象已經沒有其他對象引用它時,java的垃圾回收器會将其回收并釋放記憶體。

        一個java的heap dump檔案指的是在一個時間點上java對象的記憶體鏡像導出檔案。它包括了所有的對象、字段、原始類型和對象引用。它可以訓示當jvm産生outofmemory錯誤的情況下自動建立一個堆轉儲。

        使用eclipse mat(eclipse memory analyser),有助于圖形化基于java堆轉儲的對象引用,并提供工具以發現潛在的記憶體洩露。為了能讓java虛拟機(jvm)在發生outofmemory錯誤時生成記憶體鏡像檔案,我們可以使用-xx:+heapdumponoutofmemoryerror選項,如圖21.1所示。

        安裝eclipse mat的步驟如下:

        1)啟動eclipse,點選help -> intall new software...;

        2)點選輸入欄右側小箭頭,選擇"juno"(不同版本要找到和自己版本名稱對應的選項);

        3)等待清單更新完畢,找到并展開"general purpose tools";

        4)選中并下載下傳其中的"memory analyser (incubation)"和"memory analyser (charts)"兩項。

        5)之後根據提示進行安裝。

三、mat使用示例

        1)建立工程

        建立android 工程 "com.devdiv.test.mat_test"。并且建立如下類,然後運作該工程。

 2)分析記憶體

        要獲得.hprof記憶體鏡像檔案,你可以在程序運作過程中,切換到ddms的透視圖頁面,選中您要檢視記憶體鏡像的程序,點選“dump hprof file”即可。

Android中記憶體洩露代碼優化及檢測

圖16-1  記憶體鏡像檔案分析

        生成的hprof檔案會預設使用mat打開,選擇“leak suspects report”後,點選finish按鈕。

Android中記憶體洩露代碼優化及檢測

圖16-2  用mat打開記憶體鏡像檔案

        經過一段時間的初始化後,就能夠直覺地看到關于記憶體洩露的餅圖,如下圖所示:

Android中記憶體洩露代碼優化及檢測

圖16-3  記憶體洩露餅圖

        然後就可以檢視相關的記憶體洩露,如下圖所示:

Android中記憶體洩露代碼優化及檢測

圖16-4  記憶體洩露樹形圖

繼續閱讀