我們就需要使用mat進(jìn)行分析,打開以后如下圖,

mat下載地址:http://www.eclipse.org/mat/downloads.php
本文以單例模式 內(nèi)存泄漏為例子
public class PendingOrderManager {
private static PendingOrderManager instance;
private Context mContext;
public PendingOrderManager(Context context) {
this.mContext = context;
}
public static PendingOrderManager getInstance(Context context) {
if (instance == null) {
instance = new PendingOrderManager(context);
}
return instance;
}
}
BActivity.class
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w("TAG", "-----BActiviy onCreate---------");
setContentView(R.layout.content_main);
textView = findViewById(R.id.sex_tv);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
PendingOrderManager.getInstance(BActivity.this);
}
內(nèi)存快照查看 查找內(nèi)存泄漏
運(yùn)行后 打開BActivity 然后關(guān)閉
在Android Profile 里面查看Memory,點(diǎn)擊某一時(shí)刻,可以查看堆內(nèi)存里面存在的對(duì)象

打開BActivity 后 再關(guān)閉,此時(shí)抓取內(nèi)存快照,然后導(dǎo)出

這時(shí)候會(huì)生成一個(gè)hprof文件
導(dǎo)出以后我們會(huì)得到.hprof文件,但是這個(gè)不是mat工具用到的標(biāo)準(zhǔn)文件。我們需要使用sdk自帶的hprof-conv.exe(platform-tools文件夾下) 工具進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換以后我們就得到了mat.hprof文件
進(jìn)入Android sdk 目錄下的hprof-conv.exe 里面 執(zhí)行 hprof_conv -z
例如
C:\Users\Administrator>E:\AndroidTool\SDK\Androidsdk\platform-tools\hprof-conv.exe hprof-conv
-z E:\memory1.hprof E:\mat.hprof
如果將\hprof-conv.exe配置環(huán)境變量,則在任何地方都可以使用,比較方便
hprof-conv.exe 文件的位置
C:\Users\Administrator>E:\AndroidTool\SDK\Androidsdk\platform-tools\hprof-conv.exe
轉(zhuǎn)換之前的文件位置
E:\memory1.hprof
轉(zhuǎn)換之后的文件位置
E:\mat.hprof

- Histogram可以列出內(nèi)存中的對(duì)象,對(duì)象的個(gè)數(shù)以及大小。
- Dominator Tree可以列出那個(gè)線程,以及線程下面的那些對(duì)象占用的空間。
- Top consumers通過圖形列出最大的object。
- Leak Suspects通過MA自動(dòng)分析泄漏的原因。
點(diǎn)擊Histogram

可以看到BActivity 自身有288(Shallow Heap)大小,引用其他的對(duì)象大于4416(Retained Heap)
將鼠標(biāo)放入BActivity上面 點(diǎn)擊右鍵 選擇ListObject

選擇withoutgoing 查看BActivity 被誰引用

右鍵 選擇GcRoot 選擇exclude all..... 排除掉軟引用
虛引用等等
此時(shí) 便可看到泄露的對(duì)象 是instance

內(nèi)存快照對(duì)比 查找內(nèi)存泄漏
按照上述方法 抓取一份mainActivity 的內(nèi)存快照 和上述 打開BActivity 之后 有些泄露的快照進(jìn)行對(duì)比


選擇和泄露之后的mat 進(jìn)行對(duì)比 添加過濾條件,用包名過濾 可以發(fā)現(xiàn)泄露之前的和泄露之后的少了3個(gè)文件,便可以知道 是因?yàn)槭且驗(yàn)閱卫J?context
持有了BActivity的引用導(dǎo)致的內(nèi)存泄漏

全局查看泄露情況
從MainActivity 打開BActivity 然后再關(guān)閉BActivity
執(zhí)行以下命令
adb shell dumpsys meminfo com.demo -d
此時(shí)界面在MainActivity,可以看到還存在兩個(gè)Activity 證明 BActivity有泄露
