內(nèi)存泄露測試的整個過程如下:
在孝義等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計、成都網(wǎng)站設(shè)計 網(wǎng)站設(shè)計制作按需網(wǎng)站建設(shè),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),成都營銷網(wǎng)站建設(shè),外貿(mào)網(wǎng)站建設(shè),孝義網(wǎng)站建設(shè)費用合理。在手機(jī)里啟動被測APP并打開DDMS。
在DDMS中選中【com.example.android.hcgallery】之后單擊按鈕【show heap updates】,然后切換到標(biāo)簽頁【VM Heap】,再單擊按鈕【Cause GC】。
不斷操作APP,并觀察Heap。經(jīng)過一段時間的操作我們發(fā)現(xiàn)不論是%Used還是data object的Total Size都在不斷增加,如圖。正常情況下Total Size會穩(wěn)定在一定范圍內(nèi)。
圖 VM Heap 1
即使進(jìn)行Cause GC之后仍會繼續(xù)增加,如圖
圖 VM Heap 2
此時我們懷疑如果長期下去可能有內(nèi)存泄露的可能性,為了進(jìn)一步分析我們單擊按鈕【Dump HPROF File】,得到一個后綴為hprof的文件(生成該文件的時間較長,請耐心等待)。
使用命令hprof-conv將得到的hprof文件轉(zhuǎn)化為標(biāo)準(zhǔn)的hprof,這樣MAT才能識別。
使用MAT打開轉(zhuǎn)化之后的hprof文件,選擇圖中的【Leak Suspects Report】即可。之后你會看到一個概要信息,如圖。它只是給出一個宏觀的概念,告訴你某些問題的占比,對于分析并沒有實質(zhì)性的幫助。
單擊柱形圖標(biāo)按鈕【Histogram】會生成一個視圖,它顯示的是類實例的列表,其中Shallow Heap代表對象自身占用的內(nèi)存大小,不包括它引用的對象。Retained Heap代表當(dāng)前對象大小和當(dāng)前對象可直接或間接引用到的對象的大小總和。
在Shallow Heap列進(jìn)行從大到小的排序,我們發(fā)現(xiàn)byte[]占比大,選中之后右鍵依次選擇【List objects】>【with incoming referenes】進(jìn)行鉆取,如圖。
圖 Histogram視圖
再次按照Shallow Heap列進(jìn)行從大到小的排序,選擇一個較大的對象并依次展開它的路徑,如圖。這里我們關(guān)注自己寫的代碼,也就是com.example.android.hcgallery.ContentFragment,我們發(fā)現(xiàn)mBitmap比較可疑。這種方法適合對代碼比較熟悉的朋友。
圖 with incoming references
除了上述方法之外你也可以通過排除弱引用來分析,這樣能減少干擾因素。先按照Retained Heap從大到小排序,之后右鍵大的,依次選擇【Path To GC Roots】>【exclude weak references】,得到如圖的數(shù)據(jù)。發(fā)現(xiàn)sBitmapCache這個變量占的比例較大,可能有問題。
圖 exclude weak references
小強課堂 在Java中存在強引用、弱引用、軟引用,這里給大家做一個普及:
強引用:垃圾回收不會回收它,需要我們主動設(shè)置為null。
弱引用:顧名思義比較弱,當(dāng)垃圾回收發(fā)現(xiàn)它只具有弱引用對象時,不管當(dāng)前內(nèi)存空間是什么情況,都會進(jìn)行回收。
軟引用:如果它只具有軟引用對象時,內(nèi)存空間足夠,垃圾回收器就不會回收。但如果內(nèi)存空間不足了,就會回收。
之后排查代碼發(fā)現(xiàn)sBitmapCache是static HashMap,mBitmap使用完成之后沒有recycle掉。
最后修改代碼,在mBitmap != null時進(jìn)行mBitmap.recycle()。
這樣一步步做下來至少你不會覺得混亂,而是有規(guī)可循。另外,有些內(nèi)存泄露的分析可能沒法一次性分析出來,需要多次,這就考驗大家的耐心了。其實只要記住,分析要有規(guī)可循,耐心必不可少,任何難題都可以解決的。