案例:隱秘而低調的記憶體洩露(OOM)
本文選自《大話軟體測試》一書
記憶體洩露測試的整個過程如下:
l 在手機裡啟動被測APP並開啟DDMS。
l 在DDMS中選中【com.example.android.hcgallery】之後單擊按鈕【show heap updates】,然後切換到標籤頁【VM Heap】,再單擊按鈕【Cause GC】。
l 不斷操作APP,並觀察Heap。經過一段時間的操作我們發現不論是%Used還是data object的Total Size都在不斷增加,如圖。正常情況下Total Size會穩定在一定範圍內。
圖 VM Heap 1
l 即使進行Cause GC之後仍會繼續增加,如圖
圖 VM Heap 2
l 此時我們懷疑如果長期下去可能有記憶體洩露的可能性,為了進一步分析我們單擊按鈕【Dump HPROF File】,得到一個字尾為hprof的檔案(生成該檔案的時間較長,請耐心等待)。
l 使用命令hprof-conv將得到的hprof檔案轉化為標準的hprof,這樣MAT才能識別。
l 使用MAT開啟轉化之後的hprof檔案,選擇圖中的【Leak Suspects Report】即可。之後你會看到一個概要資訊,如圖。它只是給出一個宏觀的概念,告訴你某些問題的佔比,對於分析並沒有實質性的幫助。
圖 Leak Suspects Report
圖 概要資訊
l 單擊柱形圖示按鈕【Histogram】會生成一個檢視,它顯示的是類例項的列表,其中Shallow Heap代表物件自身佔用的記憶體大小,不包括它引用的物件。Retained Heap代表當前物件大小和當前物件可直接或間接引用到的物件的大小總和。
l 在Shallow Heap列進行從大到小的排序,我們發現byte[]佔比最大,選中之後右鍵依次選擇【List objects】>【with incoming referenes】進行鑽取,如圖。
圖 Histogram檢視
l 再次按照Shallow Heap列進行從大到小的排序,選擇一個較大的物件並依次展開它的路徑,如圖。這裡我們關注自己寫的程式碼,也就是com.example.android.hcgallery.ContentFragment,我們發現mBitmap比較可疑。這種方法適合對程式碼比較熟悉的朋友。
圖 with incoming references
l 除了上述方法之外你也可以透過排除弱引用來分析,這樣能減少干擾因素。先按照Retained Heap從大到小排序,之後右鍵最大的,依次選擇【Path To GC Roots】>【exclude weak references】,得到如圖的資料。發現sBitmapCache這個變數佔的比例較大,可能有問題。
圖 exclude weak references
小強課堂 在Java中存在強引用、弱引用、軟引用,這裡給大家做一個普及:
強引用:垃圾回收不會回收它,需要我們主動設定為null。
弱引用:顧名思義比較弱,當垃圾回收發現它只具有弱引用物件時,不管當前記憶體空間是什麼情況,都會進行回收。
軟引用:如果它只具有軟引用物件時,記憶體空間足夠,垃圾回收器就不會回收。但如果記憶體空間不足了,就會回收。
l 之後排查程式碼發現sBitmapCache是static HashMap,mBitmap使用完成之後沒有recycle掉。
l 最後修改程式碼,在mBitmap != null時進行mBitmap.recycle()。
這樣一步步做下來至少你不會覺得混亂,而是有規可循。另外,有些記憶體洩露的分析可能沒法一次性分析出來,需要多次,這就考驗大家的耐心了。其實只要記住,分析要有規可循,耐心必不可少,任何難題都可以解決的。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69942496/viewspace-2655252/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- JVM記憶體洩露(OOM)!帶你一一揭秘【第一彈】JVM記憶體洩露OOM
- JVM記憶體洩露(OOM)!帶你一一揭秘【第二彈】JVM記憶體洩露OOM
- SHBrowseForFolder 記憶體洩露記憶體洩露
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- ArkTS 的記憶體快照與記憶體洩露除錯記憶體洩露除錯
- vue 打包專案時因node記憶體洩露而報錯Vue記憶體洩露
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 實戰Go記憶體洩露Go記憶體洩露
- Android 記憶體洩露詳解Android記憶體洩露
- android Handler導致的記憶體洩露Android記憶體洩露
- nodejs爬蟲記憶體洩露排查NodeJS爬蟲記憶體洩露
- Pprof定位Go程式記憶體洩露Go記憶體洩露
- 簡單的記憶體“洩露”和“溢位”記憶體
- JAVA記憶體洩露的原因及解決Java記憶體洩露
- Python實現記憶體洩露排查的示例Python記憶體洩露
- win10驅動記憶體洩露如何解決_win10記憶體洩露處理方法Win10記憶體洩露
- netty 堆外記憶體洩露排查盛宴Netty記憶體洩露
- 乾貨分享:淺談記憶體洩露記憶體洩露
- 解決git記憶體洩露問題Git記憶體洩露
- Spring Boot heapdump洩露記憶體分析方法Spring Boot記憶體
- 線上記憶體洩露定位--memleak工具記憶體洩露
- java中如何檢視記憶體洩露Java記憶體洩露
- 記一次"記憶體洩露"排查過程記憶體洩露
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露
- 一個Vue頁面的記憶體洩露分析Vue記憶體洩露
- C程式記憶體洩露檢測工具——ValgrindC程式記憶體洩露
- Android效能最佳化之記憶體洩露Android記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- 經驗之談:記憶體洩露的原因以及分析記憶體洩露
- 記一次 .NET 某工控軟體 記憶體洩露分析記憶體洩露
- ThreadLocal原始碼解讀和記憶體洩露分析thread原始碼記憶體洩露
- 使用mtrace追蹤JVM堆外記憶體洩露JVM記憶體洩露
- 一次Kafka記憶體洩露排查經過Kafka記憶體洩露
- 前端面試題51----JS記憶體洩露前端面試題JS記憶體洩露
- 利用dotnet-dump分析docker容器記憶體洩露Docker記憶體洩露
- Android中使用Handler造成記憶體洩露的分析和解決Android記憶體洩露