Android开发进阶(从小工到专家)读书笔记——内存泄露
垃圾回收器只会移除那些不可达的对象。在代码中,若因为失误使得一个本应该被销毁的对象被错误地持有,那么该对象就不会被释放掉。
这些不可达的对象,聚集在App的堆内存中,占用App的内存空间。持续地泄露对象,会导致内存空间越来越小,GC操作越来越频繁,从而导致App变慢,降低UI流畅度,最终内存泄露快速升级为内存溢出,导致应用Crash。
使用 Memory Monitor
- 使用 Android Studio 内置的 Memory Monitor 监视内存使用情况。Memory Monitor 只能作用于正在运行的App,因此必须确保要测试的应用已经安装到设备中,同时设备已经连接到计算机上。
使用 DDMS
- 使用 Android Device Monitor 工具中的 DDMS,在 Devices 中选择要检测的 App,点击选择 Heap 标签。
内存泄露检测利器—— 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); } }

14万+

被折叠的 条评论
为什么被折叠?



