Android知识体系之异常处理-内存泄漏
Android知识体系
参考
Android内存泄露检测 LeakCanary2.0(Kotlin版)的实现原理
Android内存泄漏检测利器:LeakCanary
内存泄漏
内存泄漏(Memory Leak)指 程序在申请内存后,当该内存不需再使用但 却无法被释放 & 归还给程序的现象
本质原因
本该被回收的对象,因为某些原因而不能被回收,从而继续留在堆内存中。
- 本该被回收
业务上来说,该对象已经不再使用
- 某些原因而不能被回收
小结
当一个对象已不再被使用,本该被GC回收,但是另外一个正在使用的对象持有了它的引用,从而导致它不能被回收,留在了堆内存中。
本质原因:对象生命周期的不同。比如说:
Handler引用了Activity,导致Activity回收不成功
内存
Java基础之Java内存模型
内部类
Java基础之内部类
常见的内存泄漏
- Static 关键字修饰的成员变量
被 Static 关键字修饰的成员变量 引用耗费资源过多的实例(如Context),则容易出现该成员变量的生命周期 > 引用实例生命周期的情况,当引用实例需结束生命周期销毁时,会因静态变量的持有而无法被回收,从而出现内存泄露
- 非静态内部类
非静态内部类默认持有外部类的引用 而导致外部类无法释放,最终 造成内存泄露
例如Handler、AsyncTask、Runnable等
- 资源对象使用后未关闭
对于资源的使用(如 广播BraodcastReceiver、文件流File、数据库游标Cursor、图片资源Bitmap等),若在Activity销毁时无及时关闭 / 注销这些资源,则这些资源将不会被回收,从而造成内存泄漏
- xxx
常见的工具
Android内存检测工具
LeakCanary
LeakCanary是一个傻瓜化并且可视化的内存泄露分析工具。
简单,易于发现问题,人人可参与。
- 简单:只需设置一段代码即可,打开应用运行一下就能够发现内存泄露。而MAT分析需要Heap Dump,获取文件,手动分析等多个步骤。
- 易于发现问题:在手机端即可查看问题即引用关系,而MAT则需要你分析,找到Path To GC Roots等关系。
- 人人可参与:开发人员,测试测试,产品经理基本上只要会用App就有可能发现问题。而传统的MAT方式,只有部分开发者才有精力和能力实施。
原理
Java基础之引用类型
LeakCanary原理从0到1
- 当一个Activity的onDestory方法被执行后,说明该Activity的生命周期已经走完,在下次GC发生时,该Activity对象应将被回收。
- 通过上面对引用的学习,可以考虑在onDestory发生时创建一个弱引用指R向Activity,并关联一个RefrenceQuence,当Activity被正常回收,弱引用实例本身应该出现在该RefrenceQuence中,否则便可以判断该Activity存在内存泄漏。
- 通过Application.registerActivityLifecycleCallbacks()方法可以注册Activity生命周期的监听,每当一个Activity调用onDestroy进行页面销毁时,去获取到这个Activity的弱引用并关联一个ReferenceQuence,通过检测ReferenceQuence中是否存在该弱引用判断这个Activity对象是否正常回收。
- 当onDestory被调用后,初步观察到Activity未被GC正常回收时,手动触发一次GC,由于手动发起GC请求后并不会立即执行垃圾回收,所以需要在一定时延后再二次确认Activity是否已经回收,如果再次判断Activity对象未被回收,则表示Activity存在内存泄漏。
- 最后用HAHA这个开源库去分析dump之后的heap内存,分析内存泄露的路径
缺点
「抄底 Android 内存优化 8」 —— 快手线上 OOM 监控学习笔记
LeakCanary 有致命的问题:无法线上部署。原因很简单在采集和分析内存镜像中会造成明显的卡顿。
- 无法线上部署
- 主动触发 GC 造成 App 卡顿
- Dump 内存镜像时会造成 app 冻结(大约13s,期间不响应任何操作)
- 分析内存镜像效率低
- 不具备 service 处理能力(上传、检索、分析)
- 使用范围
- 仅能检查 Activity&Fragment泄漏
- 无法检测大对象分配、内心抖动等问题
- 自动化程度低
拾遗
使用ContentProvider初始化SDK库
Android使用ContentProvider初始化SDK库方案总结
使用ContentProvider初始化你的Library