内存抖动
含义:短时间内有大量对象进出新生区导致,表现为内存忽高忽低,分析图呈现
锯齿状。
坏处:
- 导致APP出现卡顿,严重可能导致OOM
内存泄露
含义:程序中已动态分配的堆内存由于某种原因导致内存为及时释放或无法释放,
造成内存浪费。
条件:泄露对象引用满足根可达性性,即A对象被B对象引用,但A已被销毁,B一直还存在
检测工具
- Android Profile 内存性能分析
1、可导出dump供MAT分析使用,或者在3直观判断是否存在内存泄露
2、可通过监控分析内存total值,如果total值一直在上升(一般可能是一直执行字符串创建、UI绘制里频繁创建对象导致等某些方法内对象频繁创建导致),严重可能导致OOM,这种情况需要优化
- MAT,用于分析内存泄露地方,可使用对比快照法
1、转换 Android Profile的hprof文件为MAT可识别的文件类型
cmd命令: hprof-conv 转换前名称.hprof 转换后名称.hporf
2、导入hporf文件后,具体操作如下:
3、搜索Activity相关;4、排除弱引用、软引用相关
- LeakCanary 内存泄露检测工具
作用:APP在运行时检测内存泄露,当内存泄露时生成泄露对象的引用链,发出通知告知使用者。
核心原理:通过检测Activity、Fragment等对象何时被销毁,应该被垃圾回收,把这些被销毁的对象通过ObjectWatcher 借助弱引用的方式来判断是否垃圾回收成功。
检测流程:
1> 检测保留的对象
2> 生成堆转储文件(heap dump)
3> 分析堆转储文件
4> 对泄露对象进行分类
可检测对象:
a、已销毁的Activity实例
b、已销毁的Fragment实例
c、销毁的View实例
d、已清除的ViewModel实例
检测泄露实现方案:
借助弱引用(WeakReference)和 引用队列(ReferenceQueue),如果弱引用所引用的对象被垃圾回收器回收,虚拟机会把这个弱引用加入到与之关联的引用队列中,借助此特性可用来检测一个对象是否被垃圾回收器回收成功。
规避内存泄露方法
- 避免在单例传参中使用易被销毁的上下文,比如Activity
- 避免在静态变量中引用易被销毁的上下文,比如Activity
- 避免在非静态内部类(包括匿名内部类)使用易被回收的强引用,比如:Activity中使用非静态内部类的Handler
- 避免广播未取消注册
- 避免使用Timer和TimeTask结束时,未取消监听
- 避免集合中引用强引用(比如Activity、View等)但当强引用被回收时未及时销毁集合
- 避免使用IO、db数据库操作后未关闭资源导致内存泄露
- 避免使用属性动画当界面例如Activity销毁时未取消动画导致内存泄露
- 避免WebView当界面例如Activity销毁时处理不当导致内存泄露;
- 解决方法1、使用独立进程
- 解决方法2、界面销毁时,先将WebView从父容器中移除,在执行WebView的onDestory