一、内存问题
- 内存抖动,锯齿状,GC导致卡顿
- 内存泄漏,可用内存减少,频繁GC
- 内存溢出,OOM,程序异常
二、内存分析工具
- Memory Profiler
- Memory Analyzer
- LeakCanary
Memory Profiler
- 实时图表展示应用内存使用量
- 识别内存泄露、抖动等,(简单的识别)
- 提供捕获堆转储、强制GC以及跟踪内存分配
使用方法:Android studio下面的Profiler
左上角有个加号 选择想要跟踪的进程
右边有三种类型:CPU、MEMORY、ENERGY
点击MEMORY
垃圾桶按钮:点击的话相当于一次GC
第二个按钮:将内存信息转成一个文件,以文件的方式展示出来
Record 按钮:记录点击之后在内存当中分配内存的情况 7.1及以下的版本的手机才有这个按钮
减号和加号:放大缩小总结:
- 方便直观,对于整合内存情况来说,通过图表的方式来看到,同时可以知道分配内存的情况,也可以知道分配某一个对象具体的堆栈信息以及在哪里创建的
- 线下平时使用,Android studio自带的工具在开发工程中使用
Memory Analyzer (MAT)
- 强大的Java Heap分析工具,查找内存泄露及内存占用
- 生成整体报告、分析问题等
- 线下深入使用
- 使用方式
- https://www.eclipse.org/mat/downloads.php
- 转换:hprof-conv 原文件路径 转换后文件路径
LeakCanary
- 自动内存泄露检测
- https://github.com/square/leakcanary
- 线下集成
三、Java内存管理机制
http://t.csdn.cn/ZJUWo
四、Android内存管理机制
- 内存弹性分配,分配值与最大值受具体设备影响
- OOM场景:内存真正不足、可用内存不足(整个系统都没有内存导致我们的APP OOM)
Dalvik与Art区别
- Dalvik仅固定一种回收算法,手机出厂之前、烧录之前已经确定好了,在运行期间无法改变
- Art回收算法可运行期选择(5.0之后默认使用的虚拟机)在不同的情况下可以选择合适的垃圾回收算法
- Art具备内存整理能力,减少内存空洞
案例:
应用程序发生在前台,正在与用户进行交互,对于用户来说,这时候响应速度最重要,此时应该选择一直简单的回收算法--标记清除算法,直接简单粗暴的作为前台的垃圾回收算法
如果用户将APP切换到了后台,采用标记整理算法,作为一种补充
Low Memory Killer机制
针对所有进程来说的,当手机内存不足时,这个机制会针对所有进程进行回收
Android系统将进程分为(优先级按照从高往低):
- 前台进程
- 可见进程
- 服务进程
- 后台进程
- 空进程
Low Memory Killer机制会找低优先级进程优先进行回收,在回收时会考虑一个回收收益
五、内存抖动
定义:内存频繁分配和回收导致内存不稳定
表现:频繁GC、内存曲线呈锯齿状
危害:导致卡顿、严重时,会导致OOM
内存抖动导致OOM:
- 频繁创建对象,导致内存不足及碎片(不连续)
- 不连续的内存碎片无法被分配,导致OOM
实战:
- 首先通过Memory Profile 工具进行初步排查,为什么要选这个工具,它能很直观的以图表的方式告诉我们这个App 的内存使用情况,可以直观的看到这个App 在这段使用过程中是不是呈锯齿状,有没有内存抖动的表现
- 使用Memory Profiler 的跟踪内存分配的功能,同时结合代码进行排先确认哪个地方的内存抖动,然后再去修改它。或者结合CPU Profiler 结合代码排查
解决技巧
找循环或者频繁调用的地方
六、内存泄漏
定义:内存中存在已经没有用的对象
表现:内存抖动,可用内存逐渐变少,可能代码写的有问题,不断的申请内存,系统频繁的GC,导致的内存抖动
危害:内存不足,频繁GC ,OOM
解决实战:使用Memory Profiler初步观察,通过Memory Analyzer结合代码确认
Memory Analyzer 强大的Java heap 工具,可以对Java内存进行深入分析,对于内存泄露来说,Memory profiler 只能进行一个简单的分析,并不能确认问题确认问题只能通过MAT
七、ARTHook 优雅的检测不合理图片
Bitmap内存模型
- AP110之前Bitmap自身在Dalvik Heap中,像素在Native
- API10之后像素也被放在Dalvik Heap中
- AP126之后像素在Native
获取Bitmap占用内存
- getByteCount 运行时直接获取Bitmap的内存大小
- 宽 x 高 x 一像素占用内存,如果在资源目录下还要*压缩比例,在res目录下
常规方式:
背景:图片对内存优化至关重要,图片宽高大于控件宽高
实现:继承ImageView,覆写实现计算大小
总结:侵入性强,不通用
Epic方式:
- Epic是一个虚拟机层面、以Java Method为粒度的运行时Hook框架
- 支持Android4.0一9.0
- https://github.com/tiann/epic
- 使用:
- compile 'me.weishu:epic:0.3.6'
- 继承xC_ MethodHook ,实现相应逻辑
- 注入Hook :DexposedBridge.findAndHookMethod
ARTHook
挂钩,将额外的代码钩住原有方法,修改执行逻辑
使用场景:运行时插桩,性能分析
优点:无侵入性、通用性强、
缺点:兼容问题大,开元方案不能带到线上环境