Android 内存优化指北

116 阅读3分钟

JVM内存原理

Java 内存分配区域

4f4f0aed-8faa-4039-a93a-920b9fa46e45.png

  • 方法区:主要存放静态常量
  • 虚拟机栈: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 原理解析
  • 线上内存监控研究分享