廢話不多說直接說流程
給項(xiàng)目中集成
LeakCanary
工具進(jìn)行內(nèi)存泄漏檢測繁疤。發(fā)現(xiàn)有內(nèi)存泄漏后該工具會進(jìn)行提示有內(nèi)存泄露后我們需要使用as的profiler工具進(jìn)行分析并獲取到
.hprof
文件,步驟如下
- 直接上圖
-
點(diǎn)擊如下按鈕打開profiler工具
image.png -
打開以后如下圖,
3571184-f5ba2fc11268fc54.png -
我們選擇MEMORY察蹲,進(jìn)去以后如下圖
image.png -
然后我們對有內(nèi)存泄漏的頁面進(jìn)行反復(fù)操作(為了模擬泄漏場景)济锄。然后點(diǎn)擊下圖
1
位置的垃圾桶進(jìn)行強(qiáng)制gc,再點(diǎn)擊2
的位置獲取堆棧信息
image.png -
當(dāng)堆棧信息獲取完成后聊浅,會彈出如下框餐抢,我們將排序方式選為
Arrange by package
(好定位我們自己的代碼),找到我們的代碼后我們真的發(fā)現(xiàn)狗超,應(yīng)該已經(jīng)被回收了的LoginActivity還占用這內(nèi)存。但是為什么沒有被銷毀朴下,還有那些對象引用著他努咐。這時我們就需要點(diǎn)擊位置為3
的地方,導(dǎo)出.hprof
文件進(jìn)行具體分析了
image.png 導(dǎo)出以后我們會得到
1.hprof
文件殴胧,但是這個不是mat
工具用到的標(biāo)準(zhǔn)文件渗稍。我們需要使用sdk自帶的hprof-conv.exe
(platform-tools文件夾下) 工具進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換以后我們就得到了1_mat.hprof
文件
-
轉(zhuǎn)換mat標(biāo)準(zhǔn)文件
命令:hprof-conv -z src dst
例如:hprof-conv -z 1.hprof 1_mat.hprof
- 下來我們就需要使用mat進(jìn)行分析了,打開以后如下圖团滥,我們呢點(diǎn)擊
histogram
mat下載地址:http://www.eclipse.org/mat/downloads.php
-
進(jìn)入Histogram 頁面有我們在紅框位置輸入我們想要找的類竿屹,然后右鍵選擇
merge shortest paths to Gc roots
然后在選擇exclude all phantom/weak/soft etc.references
選項(xiàng)
image.png -
就得到了如下的引用圖,從圖中我們分析出 loginActivity是被inputMethodManager所引用(這其實(shí)是android系統(tǒng)的一個bug),所以我們主要將兩者之間的聯(lián)系給斷開就行灸姊,解決方法如下
image.png 使用反射的方式將引用的view置為null
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
try {
//獲得 所有屬性 getField->public 以及父類
Field mCurRootViewField = InputMethodManager.class.getDeclaredField("mCurRootView");
//設(shè)置允許訪問權(quán)限
mCurRootViewField.setAccessible(true);
// 對象
Object mCurRootView = mCurRootViewField.get(im);
if (null != mCurRootView){
Context context = ((View) mCurRootView).getContext();
if (context == this){
//破怪gc 引用鏈
mCurRootViewField.set(im,null);
}
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}