内存泄露

Android开发进阶(从小工到专家)读书笔记——内存泄露


垃圾回收器只会移除那些不可达的对象。在代码中,若因为失误使得一个本应该被销毁的对象被错误地持有,那么该对象就不会被释放掉。
这些不可达的对象,聚集在App的堆内存中,占用App的内存空间。持续地泄露对象,会导致内存空间越来越小,GC操作越来越频繁,从而导致App变慢,降低UI流畅度,最终内存泄露快速升级为内存溢出,导致应用Crash。

使用 Memory Monitor

  • 使用 Android Studio 内置的 Memory Monitor 监视内存使用情况。Memory Monitor 只能作用于正在运行的App,因此必须确保要测试的应用已经安装到设备中,同时设备已经连接到计算机上。
    Memory Monitor 内存使用情况

使用 DDMS

  • 使用 Android Device Monitor 工具中的 DDMS,在 Devices 中选择要检测的 App,点击选择 Heap 标签。
    DDMS 内存使用情况

内存泄露检测利器—— LeakCanary

集成步骤

dependencies {
    // 省略其他代码
    debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3'
    releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3'
}

然后创建一个 Application 子类,代码如下:

public class MyApp extends Application {

    private static RefWatcher mRefWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        // LeakCanary.install返回一个RefWatcher,用于监控、跟踪应用中的对象引用。
        mRefWatcher = LeakCanary.install(this);
    }

    public static RefWatcher getRefWatcher() {
        return mRefWatcher;
    }
}

然后在 AndroidManifest.xml 中将该 MyApp 设置为应用的 Application,代码如下:

<application
    android:allowBackup="true"
    android:name=".MyApp"                            // 注意这里
    android:icon="@mipmap/ic_launcher"
    android:lable="@string/app_name"
    android:theme="@style/AppTheme">
    // 省略其他注册
</application>

这样就完成了 LeakCanary 的集成。

  这种形式实现 Activity 内存泄露的原理是在 API 14(Android 4.0)时增加了 ActivityLifecycleCallbacks,通过这个 callback 就可以监控 Activity 的生命周期。默认情况下,LeakCanary 监控所有 Activity 的生命周期,并且在 Activity 的 onDestory 函数之后将该 Activity 添加到内存泄露监控队列,也就是在 RefWatcher.watch() 中创建一个 KeyedWeakReference 到被监控的对象。
  然后在后台线程中检测这个引用是否被清除,若没有将会触发 GC。若引用仍然没被清除,将 heap 内存 dump 到一个 .hprof 文件并存放在手机系统里。HeapAnalyzerServiece 在另一个独立的进程中启动,使用 HeapAnalyzer 解析 heap 内存通过 MyApp 这个项目 HeapAnalyzer 计算出到 GC ROOTs 的最短强引用路径来决定是否发生 Leak,然后建立导致泄露的引用链。结果被回传到应用程序进程的 DisplayLeakService 中,然后输出 log 并且显示一个泄露的消息通知。
  若是 Android 4.0 以下没有 ActivityLifecycleCallbacks,则手动添加 Activity 监控,即在 Activity 的 onDestory 函数中调用 RefWatcher 的 watch 函数,例如:

public class LeakActivity extends Activity {
     // 代码省略
    @Override
    protected void onDestory() {
        super.onDestory();
        MyApp.getRefWatcher().watch(this);
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值