内存泄漏查找及分析

android 内存泄漏是个常见的问题,一不留神就出现了,内存泄漏说白了就是生命周期超了,有经验的童鞋,在写代码时就会注意了,但人无完人,难免会失手,下面就说说怎么排查内存泄漏问题。常见的无外乎两种, Android Studio 开发工具自带的 Profiler,或者直接使用 LeakCanary 开源库。先说说 Profiler。

Profiler 栏目有三个小栏目,CPU 、MEMORY 、NETWORK,分别指:CPU使用状况,内存使用状况和网络状况,内存分析选择 MEMORY,此时在它右边可以看到三个按钮:小垃圾桶、下载按钮 及 Record 按钮,分别代表 手动触发GC,垃圾回收 、 下载 Heap 堆内存文件,便于分析内存 、 记录一段时间内存的使用状况。 如果我们想检测末个 Activity 是否存在内存泄漏,那么就可以按照如下步骤操作:一、进入要检测的 Activity 里面,可以待上3秒,然后退出;二、点击垃圾桶按钮,触发GC,回收对象;三、三秒后点击下载按钮;四、等待几秒后,Android studio 会自动生成堆内存数据; 我们会看见 Heap Dump 栏位,可以按照包名来显示文件,直接找自己包名下的 Activity, 如果有内存泄漏,上面会显示出来,我们可以直观的代码定位。 上面是很方便的操作,还有另外一种操作:一、点击 Record 按钮,开始检测内存;二、进入该 Activity,3秒后退出;三、点击垃圾箱,触发GC,3秒后点击 Record 停止检测;四、等待生成内存数据信息,根据信息排查。


上面是开发工具自带的检查工具,从上面看到,我们需要手动触发GC,也就是进行一次内存回收,理由也简单,退出该页面了,并且也内存回收了,如果它里面还与对象存在,那就说明还有引用,并且是强引用,那自然就是内存泄漏了。其实 LeakCanary 也是这么个原理,只是它默认仅检测 Activity 的,看下它的代码,发现它在 Application 中注册了 registerActivityLifecycleCallbacks() 回调事件,在 onActivityDestroyed() 方法中对该 Activity 添加了弱引用,然后通过代码触发 GC,接着就在垃圾列表中查找是否还有该 Activity 以便于分享是否内存泄漏,其实原理和 Profiler 一样,如果我们想监听其它对象,则需要自己手动添加。 在 Application 中 执行 LeakCanary.install(this) 时,会返回一个对象 refWatcher ,然后拿到它,把需要监听的对象传进去, 比如一个 ImageView iv, 可以 refWatcher.watch(iv); 这样就可以了。


说到引用,接触最多的应该就是强引用和弱引用了,new 一个对象,是强引用;WeakReference 是弱引用,一般为了防止内存泄漏才用到它。强引用是宁可OOM也不会被回收,弱引用则是由系统判断,gc 时很容易就回收了。这句话没毛病,但有些人理解错了,当对象 A 被弱引用持有,它是很容易被回收;如果它同时被成员变量和弱引用持有,那么此时 GC 了,弱引用也不会被回收,比如:

    WeakReference<Object> reference;
    @Override
    protected void onResume() {
        super.onResume();
        ImageView iv = new ImageView(this);
        reference = new WeakReference<Object>(iv);
        Log.e("WeakReference", "onResume reference  " + reference.get());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("WeakReference", "onDestroy reference  " + reference.get());
    }

我们创建了个 iv,但它是局部变量,我们看到打印日志 onResume 中有值,onDestroy 中被置空了;但如果我们把 iv 变为成员变量,如下

    ImageView iv;
    WeakReference<Object> reference;
    @Override
    protected void onResume() {
        super.onResume();
        iv = new ImageView(this);
        reference = new WeakReference<Object>(iv);
        Log.e("WeakReference", "onResume reference  " + reference.get());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.e("WeakReference", "onDestroy reference  " + reference.get());
    }

 onResume 中有值,onDestroy 中也有值,这就说明了弱引用的回收时机。LeakCanary 就是根据这个来判断是否与内存泄漏的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值