1. 程式人生 > >記憶體洩漏檢測分析工具

記憶體洩漏檢測分析工具

monkey 工具測試應用

可以使用monkey自動化測試工具快速不斷的操作應用。終端指令:

// 300 毫秒一個事件,2000個事件,跑10分鐘
adb shell monkey -p com.android.deskclock -v --throttle 300 --ignore-crashes --ignore-security-exceptions --ignore-timeouts 2000

引數說明:

adb shell monkey 2000           // 2000個隨機事件
-p                              // 指定包名
-v                              // 日誌級別 -v/-v -v/-v -v -v
--throttle 300 // 事件間隔時間 --ignore-crashes // 忽略應用crash資訊,繼續執行 --ignore-security-exceptions // 忽略安全異常 --ignore-timeouts //

Android divece monitor 獲取hprof檔案

使用Android studio的divece monitor工具,或者 DDMS 工具可以獲得hprof檔案。
hprof檔案是虛擬機器的記憶體快照,包含某一時刻虛擬機器記憶體佔用情況資訊。

Markdown


1. 使用eng版本(root後的)手機連線電腦,開啟 ddms 工具,在左側選中自己應用的程序。
2. 在右側介面多個tab頁中選中 heap tab 頁。
3. 點選選擇 update heap 按鈕,之後 heap 資料會自動更新。按鈕在左上方。
4. 點選cause GC 按鈕執行一次 GC , 介面上資料會顯示出來。
5. 跑了一段時間 monkey 後,就可以dump hprof 檔案了。點選左上角按鈕5 dump hprof file ,一個短暫的延遲後,會彈出選擇儲存檔案位置的彈框。

儲存下來的hprof檔案無法直接用 MAT 開啟,需要使用 Android hprof-conv 工具轉換為標準的 hprof 格式檔案。這個工具在Android/Sdk/platform-tools

目錄下,使用方法:

$ ./hprof-conv ~/path/before.hprof ~/path/after.hprof

使用 MAT(Memory analysis tool)分析 hprof檔案

工具下載地址:http://www.eclipse.org/mat/downloads.php

MAT 是一個記憶體分析工具,它不會為你指出具體哪一塊程式碼導致了記憶體洩露,需要我們自己根據記憶體資訊分析出問題點。

Markdown

使用 MAT 開啟 hprof 檔案,主介面是一個展示記憶體佔用比例的餅圖,我們主要使用左下兩個圈紅的功能進行記憶體分析。

  • Histogram : 該操作可以列出 heap 中每個類的例項個數。
  • Dominator Tree : 該操作可以列出佔用記憶體最大的物件,以及該物件被誰所引用導致不能釋放。

jvm 判斷物件是否存活採用的是可達性分析演算法,演算法的基本思路就是通過一系列稱為 “GC roots” 的物件作為起始點,從這些節點開始向下搜尋,搜尋所走過的路徑稱為引用鏈,當一個物件到GC Roots沒有任何引用鏈相連時,則證明此物件是不可用的。

所以我們分析的目標就是找出那些不應該存在的物件例項,以及是什麼引用了它們導致不能釋放。

Markdown

開啟 Histogram 檢視,並在正則表示式欄中輸入本專案相關的匹配資訊,檢視類例項的數量。從圖中可以看出,一個首頁Activity居然同時有9個例項,這明顯是不正常的,說明有什麼導致了Activity的例項沒有被回收。

Dominator Tree View :

Markdown

Dominator Tree 有兩列展示 heap 大小:
- shallow heap : 物件真實佔用的記憶體大小
- retained heap : 該物件被回收,可能所能釋放的最大記憶體大小

如圖,選中一 retained heap 遠大於 自身 shallow heap 的物件,檢視物件到GC Roots的引用路徑。(將軟引用,弱引用等忽略,因為只有強引用會導致物件無法回收)
Markdown

可以明確看出物件的引用路徑,我們需要根據物件引用資訊,去程式碼中找到具體的使用不當的地方,然後修復。比如這個例子是因為 EventBus 持有了 Activity 的例項沒有釋放,導致Activity的資源都無法釋放。