分析工具
android studio
當(dāng)前使用版本:android studio 3.4
android studio 提供了Profiler工具可以提供可視化的內(nèi)存觀察,以及堆轉(zhuǎn)儲的功能跃脊。在實(shí)際使用過程中感覺太繁瑣,因?yàn)槲覀儧]法確定是哪個頁面發(fā)生了內(nèi)存泄漏颖侄,所以就引用了LeakCanary
2.LeakCanary
當(dāng)前使用版本:com.squareup.leakcanary:leakcanary-android:1.6.3
引用官方的一句話"A memory leak detection library for Android"衣屏,LeakCanary能幫我們動態(tài)監(jiān)控內(nèi)存泄漏耕赘,以及發(fā)生在哪個頁面,同時(shí)還能自動的完成堆轉(zhuǎn)儲
3.MAT
當(dāng)前使用版本:Eclipse Memory Analyzer Version 1.8.1
引用官方的一句話"The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.",MAT是一個功能強(qiáng)大的Java堆分析器
內(nèi)存泄漏代碼
- MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_no_static_class).setOnClickListener(v -> startActivity(new Intent(MainActivity.this, NoStaticClassActivity.class)));
}
- NoStaticClassActivity
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_no_static_class);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.d(TAG, Thread.currentThread().getName());
}
}, 1000 * 60 * 10);
finish();
}
分析
-
LeakCanary自動捕獲到了信息:
Screenshot_20190516-111448_LeakCanaryDemo.jpg
這個Demo比較簡單贞绳,其實(shí)通過LeakCanary就可以分析出問題出現(xiàn)在什么地方谷醉,當(dāng)內(nèi)容比較復(fù)雜時(shí)LeakCanary并沒有那么直觀的看出內(nèi)存泄漏的原因,還是需要使用MAT工具
- MAT分析.hprof文件
LeakCanary會自動的將泄漏信息保存到手機(jī)的\Download\leakcanary-xxxx\目錄下,將該目錄下的.hprof文件復(fù)制到電腦冈闭,這個文件還不能直接用MAT工具打開俱尼,需要執(zhí)行下面的一段命令,轉(zhuǎn)換成能正常打開的文件
hprof-conv.exe .\2019-05-16_11-13-28_699.hprof handle.hprof
將轉(zhuǎn)換好的handle.hprof文件使用MAT打開就會看見下面界面
然后點(diǎn)擊用紅色圈圈起來的Histigram萎攒,會看到下面的界面
然后在紅色框中輸入我們要分析的類名遇八,在LeakCanary的界面中已經(jīng)很明確的知道是NoStaticClassActivity這個類發(fā)生了泄漏,所以在框中輸入NoS點(diǎn)擊回車就會列來耍休,右鍵點(diǎn)擊我們搜索出來的類名
點(diǎn)擊后就會跳轉(zhuǎn)到下面界面
這樣我們就非常明確的看到了Thread持有了NoStaticClassActivity的應(yīng)用刃永,從中可以看到有MessageQueue,Message會很快想到和Handler有關(guān)羹应,然后在分析具體代碼揽碘。
解決之后的代碼
- NoStaticClassActivity
private final Handler mHandler = new MyHandle();
private static class MyHandle extends Handler{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
}
在去點(diǎn)擊按鈕發(fā)現(xiàn)內(nèi)存泄漏已經(jīng)被我們修復(fù)了,本文重要的是說明工具的使用,代碼有不嚴(yán)謹(jǐn)?shù)牡胤秸堈徑?/p>