1 內(nèi)存泄漏的排查方法
Dalvik Debug Monitor Server (DDMS) 是 ADT插件的一部分灸叼,其中有兩項功能可用于內(nèi)存檢查 :
· heap 查看堆的分配情況
· allocation tracker跟蹤內(nèi)存分配情況
DDMS 這兩項功能有助于找到內(nèi)存泄漏的操作行為。
Eclipse Memory Analysis Tools (MAT) 是一個分析 Java堆數(shù)據(jù)的專業(yè)工具流部,用它可以定位內(nèi)存泄漏的原因关摇。
工具地址 : https://www.eclipse.org/mat/
1.1 觀察 Heap
· 運行程序捻脖,然后進入 DDMS管理界面,如下:
來更新統(tǒng)計信息
點擊右側(cè)的 Cause GC 按鈕或工具欄上的 [
即可查看當前的堆情況擦盾,如下:
主要關(guān)注兩項數(shù)據(jù):
o Heap Size 堆的大小窗怒,當資源增加,當前堆的空余空間不夠時吏恭,系統(tǒng)會增加堆的大小拗小,若超過上限 (例如64M,視平臺和具體機型而定)則會被殺掉
o Allocated 堆中已分配的大小樱哼,這是應(yīng)用程序?qū)嶋H占用的內(nèi)存大小哀九,資源回收后,此項數(shù)據(jù)會變小
· 查看操作前后的堆數(shù)據(jù)搅幅,看是否有內(nèi)存泄漏 對單一操作(比如添加頁阅束,刪除頁)進行反復操作,如果堆的大小一直增加茄唐,則有內(nèi)存泄漏的隱患息裸。
1.2 利用MAT分析內(nèi)存堆
DDMS 可以將當前的內(nèi)存 Dump成一個 hprof格式的文件,MAT 讀取這個文件后會給出方便閱讀的信息沪编,配合它的查找呼盆,對比功能,就可以定位內(nèi)存泄漏的原因蚁廓。
· 獲取 hprof文件 點擊工具欄上的
· 轉(zhuǎn)換 hprof文件 DDMS Dump 出的文件要經(jīng)過轉(zhuǎn)換才能被 MAT識別,Android SDK提供了這個工具 hprof-conv (位于 sdk/tools下)
· ./hprof-conv xxx-a.hprof xxx-b.hprof
· 用 MAT打開轉(zhuǎn)換后的 hprof文件
1.3 Histogram 查詢
用的最多的功能是 Histogram,點擊 Actions下的 Histogram項將得到 Histogram結(jié)果:
它按類名將所有的實例對象列出來圈匆,可以點擊表頭進行排序,在表的第一行可以輸入正則表達式來匹配結(jié)果 :
在某一項上右鍵打開菜單選擇 list objects ->with incoming refs 將列出該類的實例:
它展示了對象間的引用關(guān)系漠另,比如展開后的第一個子項表示這個 HomePage(0x420ca5b0)被HomePageContainer(0x420c9e40)中的 mHomePage屬性所引用.
快速找出某個實例沒被釋放的原因,可以右健 Path to GC Roots-->exclue all phantom/weak/soft etc. reference :
得到的結(jié)果是:
從表中可以看出 PreferenceManager -> … ->HomePage這條線路就引用著這個 HomePage實例跃赚。用這個方法可以快速找到某個對象的 GC Root,一個存在 GC Root的對象是不會被 GC回收掉的.
1.4 Histogram 對比
為查找內(nèi)存泄漏笆搓,通常需要兩個 Dump結(jié)果作對比,打開 Navigator History面板纬傲,將兩個表的 Histogram結(jié)果都添加到 Compare Basket中去 :
添加好后满败,打開 Compare Basket面板,得到結(jié)果:
點擊右上角的 ! 按鈕叹括,將得到比對結(jié)果:
注意算墨,上面這個對比結(jié)果不利于查找差異,可以調(diào)整對比選項:
再把對比的結(jié)果排序汁雷,就可得到直觀的對比結(jié)果:
也可以對比兩個對象集合净嘀,方法與此類似,都是將兩個 Dump結(jié)果中的對象集合添加到Compare Basket中去對比侠讯。找出差異后用 Histogram查詢的方法找出 GC Root挖藏,定位到具體的某個對象上。
1.5 例子
舉例一個典型的分析內(nèi)存泄漏的過程:
- 使用 Heap查看當前堆大小為 23.00M
- 添加一個頁后堆大小變?yōu)?23.40M
- 將添加的一個頁刪除厢漩,堆大小為 23.40M
- 多次操作膜眠,結(jié)果仍相似,說明添加/刪除頁存在內(nèi)存泄漏 (也應(yīng)注意排除其它因素的影響)
- Dump 出操作前后的 hprof 文件 (1.hprof,2.hprof)溜嗜,用 mat打開,并得到 histgram結(jié)果
- 使用 HomePage字段過濾 histgram結(jié)果宵膨,并列出該類的對象實例列表,看到兩個表中的對象集合大小不同炸宵,操作后比操作前多出一個 HomePage辟躏,說明確實存在泄漏
- 將兩個列表進行對比,找出多出的一個對象焙压,用查找 GC Root的方法找出是誰串起了這條引用線路鸿脓,定位結(jié)束
PS :
· 很多時候堆增大是 Bitmap引起的,Bitmap在 Histogram中的類型是 byte [],對比兩個 Histogram中的 byte[]對象就可以找出哪些 Bitmap有差異
· 多使用排序功能涯曲,對找出差異很有用
2 內(nèi)存泄漏的原因分析
總結(jié)出來只有一條: 存在無效的引用! 良好的模塊設(shè)計以及合理使用設(shè)計模式有助于解決此問題野哭。
3 Tips
· 使用 android:largeHeap="true"標記 (API Level >= 11) 在 AndroidManifest.xml中的 Application節(jié)點中聲明即可分配到更大的堆內(nèi)存, android:largeHeap標記在 Android系統(tǒng)應(yīng)用中也有廣泛的應(yīng)用 ,比如 Launcher, Browser這些內(nèi)存大戶上均有使用.
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
同事起草,整理分享幻件,可以轉(zhuǎn)載收錄拨黔。
來自:http://blog.csdn.net/aaa2832/article/details/19419679