JVM内存原理
Java 内存分配区域:
- 方法区:主要存放静态常量
- 虚拟机栈:Java变量引用
- 本地方法栈:native变量引用
- 堆:对象
- 程序计数器:计算当前线程的当前方法执行到多少行
引用:
- 强引用:发生 gc 的时候不会被回收。new
- 软引用:在发生内存溢出之前会被回收。SoftReference
- 弱引用:在下一次GC时会被回收。WeakReference
- 虚引用:无法通过虚引用获得对象,用 PhantomReference 实现虚引用,虚引用的用途是在 gc 时返回一个通知。
强引用 -> 软引用 -> 弱引用 -> 虚引用
Java 内存回收算法:
- 标记-清除算法
- 复制算法
- 标记-整理算法
- 分代收集算法
Android 内存管理机制:
- Dalivk 仅固定一种回收算法:标记-清除算法(老旧的方案
- ART 回收算法:运行期按需选择,弹性分配
- ART 具备内存整理能力,减少内存空洞
内存会造成的问题
- 内存抖动:内存波动图形呈 锯齿张、GC导致卡顿(模拟内存抖动,循环或频繁被调用
- 内存泄漏:在当前应用周期内不再使用的对象被GC Roots引用,导致不能回收,使实际可使用内存变小(案例,单例模式的对象生命周期
- 内存溢出:OOM,多为图片处理不当
优化内存的意义
- 减少OOM,提高应用稳定性
- 减少卡顿,提高应用流畅度
- 减少内存占用,提高应用后台运行时的存活率
- 减少异常发生和代码逻辑隐患
优化建议
-
频繁的字符串拼接用 stringBuilder
-
service 少用,建议使用 IntentServcie
-
Webview 新进程
-
如果代码抽象,带来更多的映射成本,需要衡量
-
资源复用:ondraw、getView 中创建的对象尽量进行复用
-
ArrayMap 来替代 HashMap
-
Bitamap: 当显示小图片或对图片质量要求不高时可以考虑使用RGB_565,用户头像或圆角图片一般可以尝试ARGB_4444
-
静态变量:避免长生命周期对象持有了短生命周期对象的引用
-
Handler 临时性内存泄漏
-
资源未释放
- 注销 BroadcastReceiver
- 关闭数据库游标
- 关闭流
- Bitmap.recycle
-
Toast 的 context
-
LeakCanary 监控、Memory Profiler等
-
谨慎使用第三方库
-
BaseBoxWidget中新增doOnRenderUISuccess方法,回收不必要的资源 -
前台每隔 3 分钟去获取当前应用内存占最大内存的比例,超过设定的危险阈值(如80%)则主动释放应用 cache(Bitmap 为大头),并且显示地除去应用的 memory,以加速内存收集的过程。
计算当前应用内存占最大内存的比例的代码如下:
max = Runtime.getRuntime().maxMemory(); available = Runtime.getRuntime.totalMemory() - Runtime.getFreeMemory(); ratio = available / max;显示地除去应用的 memory,以加速内存收集过程的代码如下所示:
WindowManagerGlobal.getInstance().startTrimMemory(TRIM_MEMORY_COMPLETE);
画个饼:
- LeakCanary 原理解析
- 线上内存监控研究分享