Android Profiler工具和mat进行内存泄漏分析

我们就需要使用mat进行分析,打开以后如下图,


image.png

mat下载地址:http://www.eclipse.org/mat/downloads.php

本文以单例模式 内存泄漏为例子

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);
    }

内存快照查看 查找内存泄漏

运行后 打开BActivity 然后关闭

在Android Profile 里面查看Memory,点击某一时刻,可以查看堆内存里面存在的对象


image.png

打开BActivity 后 再关闭,此时抓取内存快照,然后导出


image.png

这时候会生成一个hprof文件

导出以后我们会得到.hprof文件,但是这个不是mat工具用到的标准文件。我们需要使用sdk自带的hprof-conv.exe(platform-tools文件夹下) 工具进行转换,转换以后我们就得到了mat.hprof文件

进入Android sdk 目录下的hprof-conv.exe 里面 执行 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配置环境变量,则在任何地方都可以使用,比较方便

hprof-conv.exe 文件的位置
C:\Users\Administrator>E:\AndroidTool\SDK\Androidsdk\platform-tools\hprof-conv.exe
转换之前的文件位置
 E:\memory1.hprof 
转换之后的文件位置
E:\mat.hprof
image.png
  • Histogram可以列出内存中的对象,对象的个数以及大小。
  • Dominator Tree可以列出那个线程,以及线程下面的那些对象占用的空间。
  • Top consumers通过图形列出最大的object。
  • Leak Suspects通过MA自动分析泄漏的原因。

点击Histogram

image.png

可以看到BActivity 自身有288(Shallow Heap)大小,引用其他的对象大于4416(Retained Heap)

将鼠标放入BActivity上面 点击右键 选择ListObject


image.png

选择withoutgoing 查看BActivity 被谁引用

image.png

右键 选择GcRoot 选择exclude all..... 排除掉软引用
虚引用等等

此时 便可看到泄露的对象 是instance


image.png

内存快照对比 查找内存泄漏

按照上述方法 抓取一份mainActivity 的内存快照 和上述 打开BActivity 之后 有些泄露的快照进行对比


image.png
image.png

选择和泄露之后的mat 进行对比 添加过滤条件,用包名过滤 可以发现泄露之前的和泄露之后的少了3个文件,便可以知道 是因为是因为单例模式 context
持有了BActivity的引用导致的内存泄漏

全局查看泄露情况

从MainActivity 打开BActivity 然后再关闭BActivity
执行以下命令
adb shell dumpsys meminfo com.demo -d

此时界面在MainActivity,可以看到还存在两个Activity 证明 BActivity有泄露


推荐阅读更多精彩内容