内存优化介绍及工具选择
目录
- 内存优化介绍
- 优化工具选择
背景介绍
- 内存是大问题但缺乏关注
- 压死骆驼的最后一根稻草
内存问题
- 内存抖动:锯齿状、GC导致卡顿
- 内存泄漏:可用内存减少、频繁GC
- 内存溢出:OOM、程序异常
工具选择
Memory Profiler
- 实时图表展示应用内存使用量
- 识别内存泄漏、抖动等
- 提供捕获堆转储、强制GC以及跟踪内存分配的能力
- 方便直观
- 线下平时使用
Memory Analyzer
- 强大的JavaHeap分析工具,查找内存泄漏以及内存占用
- 生成整体报告、分析问题等
- 线下深入使用
LeakCanary
- 自动内存泄漏检测
- https://github.com/square/leakcanary
- 线上集成
总结
- 内存问题及工具选择
Android内存管理机制
目录
- Java内存管理机制
- Android内存管理机制
Java内存分配
方法区、虚拟机栈、本地方法栈、堆、程序计数器
Java内存回收算法
- 标记-清除算法
- 标记出所有需要回收的对象
- 统一回收所有被标记的对象
标记-清除算法
小结
1.标记清除效率不高
2.产生大量不连续的内存碎片
复制算法
将内存划分为大小相等的两块
一块内存用完之后复制存活对象到另一块
清理另一块内存
小结
1.实现简单,运行高效
2.浪费一半空间代价大
标记-整理算法
标记过程与标记“清除算法”一样
存活对象往一端进行移动
清理其余内存
小结
避免标记-清理导致的内存碎片
避免复制算法的空间浪费
分代收集算法
结合多种收集算法优势
新生代对象存活率低,复制
老年代对象存活率高,标记-整理
Android内存管理机制
- 内存弹性分配,分配数值与最大值受具体设备影响
- OOM场景:内存真正不足、可用内存不足
Dalvik与ART区别
- Dalvik仅固定一种回收算法
- Art回收算法可运行期选择
LowMemoryKiller
- 进程分类(前台、可见、服务、后台、空进程)(高到低)
- 回收收益
总结
Java及Android内存管理机制
内存抖动解决实战
目录
- 内存抖动介绍
- 内存抖动解决实战
- 总结
内存抖动介绍
- 定义:内存频繁分配和回收导致内存不稳定
- 表现:频繁GC、内存曲线层锯齿状
- 危害:导致卡顿、OOM
内存抖动导致OOM
- 频繁创建对象,导致内存不足及碎片(不连续)
- 不连续的内存片无法分配(导致OOM)
内存抖动解决实战
- 使用MemoryProfiler初步排查
- 使用Memory Profiler或CPU Profiler结合代码排查
内存抖动解决技巧
- 找循环或频繁调用的地方
总结
- 内存抖动
- 内存抖动解决实战
内存泄漏解决实战
目录
- 内存泄漏介绍
- 内存泄漏解决实战
- 总结
内存泄漏介绍 - 定义:内存中存在已经没有用的对象
- 表现:内存抖动、可用内存逐渐变少
- 危害:内存不足、GC频繁、OOM
Memory Analyzer
- https://www.eclipse.org/mat/downloads.php
- 转换:hprof-conv 原文件路径 转换后文件路径
小结
- 使用Memory Profiler初步观察
- 通过MemoryAnalyzer结合代码确认
全面理解MAT
ARTHook优雅检测不合理图片
目录
- Bitmap内存模型
- 常规方式
- ARTHook介绍
Bitmap内存模型
- API10之前Bitmap自身在Dalvik Heap中,像素在Native
- API10之后像素也被放在Dalvik Heap中
- API26之后像素在Native中
- 获取Bitmap占用内存
- getByteCount
- 宽高一像素占用内存
常规方式
- 背景:图片对内存优化至关重要、图片宽高大于控件宽高
- 实现:继承ImageView,覆写实现计算大小
- 侵入性强
- 不通用
ARTHook介绍
- 挂钩,将额外的代码钩住原有方法,修改执行逻辑
- 运行时插桩
- 性能分析
Epic简介(替代c hook)
- Epic是一个虚拟机层面、以Java Method为粒度的运行时Hook框架
- 支持Android4.0-9.0
- https://github.com/tiann/epic
Epic使用
- compile ‘me.weishu:epic:0.3.6’
- 继承XC_MethodHook,实现相应逻辑
- 注入Hook:DexposedBridge.findAndHookMethod
public class ImageHook extends XC_MethodHook{
//伪代码
afterHookMethod(MethodHookParam param){
super
//实现我们的逻辑
ImageView imageView=(ImageView)param.thisObject;
checkBitmap(imageView,imageView.getDrawable())
}
}
ARTHook实现
- 无侵入性
- 通用性强
- 兼容问题大,开源方案不能带到线上环境
线上内存监控方案
- 常规实现
- leakCanary定制
- 完整方案
常规实现一
设定场景线上Dump:Debug.dumpHprofData();
常规实现流程
超过最大内存80%->内存Dump->回传文件(wifi上传)->MAT手动分析
方案一总结
Dump文件太大,和对象数正相关,可裁剪
上传失败率高,分析困难
配合一定策略,有一定效果
常规实现方案二
集成leakCanary带到线上
预设泄漏怀疑点
发现泄漏回传
方案二总结
不适合所有情况,必须预设怀疑点
分析比较耗时、也容易OOM
LeakCanary原理
监控生命周期,onDestroy添加RefWatcher检测
二次确认断定发生内存泄漏
分析泄漏,找引用链
监控组件,分析组件
LeakCanary定制
预设怀疑点->自动找怀疑点
分析泄漏链路慢->分析RetainSize大的对象
分析OOM->对象裁剪,不全部加载到内存
线上监控完整方案
待机内存、重点模块内存、OOM率
整体及重点模块GC次数、GC时间
增强的LeakCanary自动化内存泄漏分析
总结
线上内存泄漏监控的常规方案
线上内存监控的完整方案
内存优化技巧总结
优化大方向【方便简单好做见效快】
- 内存泄漏
- 内存抖动
- Bitmap
优化细节
LargeHeap属性(申请更多内存)
lowMemoryKiller
onTrimMemory
使用优化过的集合:SparseArray
谨慎使用SharedPreference
谨慎使用外部库
业务架构设计合理(省市区)