使用Android Studio 查看内存泄漏

用新版的AS 的profiler 查看内存泄漏

记录一下使用Android Studio 的profiler 查看内存泄漏的过程。新版的AS 的profiler 功`能强大。我们可以很方便的查看到一个界面里的内存泄漏。

首先我们来看看不发生内存泄漏时候的情况:


public class MemoryLeakActivity extends AppCompatActivity {

    private ValueAnimator count20sToStop;

// 这里有在onDestory里处理,这样做肯定会避免掉当前情况下handler的内存泄露
    @Override
    protected void onDestroy() {
        super.onDestroy();
          mHandle.removeMessages(FLAG);
    }

    private static int FLAG = 999;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_memory_leak);

        Button btn = findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

       mHandle.sendEmptyMessageDelayed(FLAG, 1000);
    }


    private Handler mHandle = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            mHandle.sendEmptyMessageDelayed(FLAG, 1000);
        }
    };
}

在这里插入图片描述
确实没有泄露的地方。

然后我们制造一个内存泄漏的Activity。 把onDestory去掉。肯定会发生内存泄漏的。

public class MemoryLeakActivity extends AppCompatActivity {

    private static int FLAG = 999;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_memory_leak);

        Button btn = findViewById(R.id.btn);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });

        mHandle.sendEmptyMessageDelayed(FLAG, 1000);

    }


    private Handler mHandle = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            mHandle.sendEmptyMessageDelayed(FLAG, 1000);
        }
    };

 
}

然后点开AS 的profiler
在这里插入图片描述
然后我们可以查看到我们应用运行时候的cpu 内存等数据的情况。这里我们只要关注内存即可。
在这里插入图片描述

接下来我们从启动页面跳转到有内存泄漏的那个Activity。

在这里插入图片描述
这里可以看到我们从LunchActivity 跳转到了MemoryLeakActivity。

接下来我们点击button finish()掉 MemoryLeakActivity。回到我们原来的起动页面。这时候点垃圾桶,触发几次gc。

在这里插入图片描述

这些小垃圾桶就代表我们触发的gc.

在这里插入图片描述

然后选取record 来记录我们产生的内存泄漏。

在这里插入图片描述
新版的AS的Record 点一下就可以为我们自动记录一段内存快照。然后直接弹出我们的内存数据。不用像以前一样你需要拉一段距离。

这里很清晰的给我们指出有2出内存泄漏。

在这里插入图片描述

点一下这个 2 Leaks 就会直接显示出内存泄漏的类的包名位置(非常人性化)。

在这里插入图片描述
这里我们看到内存泄漏的位置一个是我们自己的Activity里Handler 造成的内侧泄漏。一处是系统里ReportFragment发生的内侧泄漏。 这个估计也跟Handler 有关。

然后我们点到相关的类还可以进一步查看内存泄漏的类的引用关系

在这里插入图片描述

使用MemoryAnalyzer

我们也可以导出内存快照。使用mat来进行内存分析。

在这里插入图片描述

首先使用 hprof-conv.exe 来转换一下我们导出的内存快照。记得把platform-tools 配置到环境变量里你才能找到hprof-conv 这个命令。

在这里插入图片描述

 hprof-conv -z 1.hprof 1-mat.hprof

生成一个新文件

在这里插入图片描述

打开Mat 导入 1-mat.hprof : file->Open Dump Heap 。 点击finish

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
这里 Shallow Size是对象本身占据的内存的大小,不包含其引用的对象。对于常规对象(非数组)的Shallow Size由其成员变量的数量和类型来定,而数组的ShallowSize由数组类型和数组长度来决定,它为数组元素大小的总和。

Retained Size=当前对象大小+当前对象可直接或间接引用到的对象的大小总和。(间接引用的含义:A->B->C,C就是间接引用) ,并且排除被GC Roots直接或者间接引用的对象。

我们进一步操作排除软引用,弱引用,虚引用看看剩下哪些东西。

在这里插入图片描述
然后我们就可以看到排除完软引用,弱引用,虚引用后内存里剩下的对象。根据剩余的对象来分析内存泄漏。

整体来看Mat 不如新版AS的profiler好用。新版AS的profiler基本上算是傻瓜式的使用了。只要目前看在安卓开发中只要会用新版AS 的profiler 即可。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值