首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Android 内存优化实践与总结(1)

Android 内存优化实践与总结(1)

导语智能手机发展到今天已经有十几个年头,手机的软硬件都已经发生了翻天覆地的变化,特别是 Android 阵营,从一开始的一两百 M 到今天动辄 4G,6G 内存。然而大部分的开发者观看下自己的异常上报系统,还是会发现各种内存问题仍然层出不穷,各种 OOM 为 crash 率贡献不少。Android 开发发展到今天也是已经比较成熟,各种新框架,新技术也是层出不穷,而内存优化一直都是 Android 开发过程一个不可避免的话题。 恰好最近做了内存优化相关的工作,这里也对 Android 内存优化相关的知识做下总结。
在开始文章之前推荐下公司同事翻译整理版本,因为篇幅有限这里我对一些内容只做简单总结,同时如果有不正确内容也麻烦帮忙指正。
本文将会对 Android 内存优化相关的知识进行总结以及最后案例分析(一二部分是理论知识总结,你也可以直接跳到第三部分看案例):
一、Android 内存分配回收机制
二、Android 常见内存问题和对应检测,解决方式。
三、JOOX 内存优化案例
四、总结
工欲善其事必先利其器,想要优化 App 的内存占用,那么还是需要先了解 Android 系统的内存分配和回收机制。
一、Android 内存分配回收机制参考 Android 操作系统的内存回收机制[1],这里简单做下总结:
从宏观角度上来看 Android 系统可以分为三个层次:
  • Application Framework
  • Dalvik 虚拟机
  • Linux 内核。
这三个层次都有各自内存相关工作:
1. Application FrameworkAnroid 基于进程中运行的组件及其状态规定了默认的五个回收优先级:

  • Empty process(空进程)
  • Background process(后台进程)
  • Service process(服务进程)
  • Visible process(可见进程)
  • Foreground process(前台进程)
系统需要进行内存回收时最先回收空进程,然后是后台进程,以此类推最后才会回收前台进程(一般情况下前台进程就是与用户交互的进程了,如果连前台进程都需要回收那么此时系统几乎不可用了)。
由此也衍生了很多进程保活的方法(提高优先级,互相唤醒,native 保活等等),出现了国内各种全家桶,甚至各种杀不死的进程。
Android 中由 ActivityManagerService 集中管理所有进程的内存资源分配。
2. Linux 内核
参考阿里巴巴的 Android 内存优化分享[2],这里最简单的理解就是ActivityManagerService会对所有进程进行评分(存放在变量 adj 中),然后再讲这个评分更新到内核,由内核去完成真正的内存回收(lowmemorykiller, Oom_killer)。这里只是大概的流程,中间过程还是很复杂的,有兴趣的同学可以一起研究,代码在系统源码ActivityManagerService.java中。
3. Dalvik 虚拟机Android 进程的内存管理分析[3],对 Android 中进程内存的管理做了分析。
Android 中有 Native Heap 和 Dalvik Heap。Android 的 Native Heap 言理论上可分配的空间取决了硬件 RAM,而对于每个进程的 Dalvik Heap 都是有大小限制的,具体策略可以看看 android dalvik heap 浅析[4]。
Android App 为什么会 OOM 呢?其实就是申请的内存超过了 Dalvik Heap 的最大值。这里也诞生了一些比较”黑科技”的内存优化方案,比如将耗内存的操作放到 Native 层,或者使用分进程的方式突破每个进程的 Dalvik Heap 内存限制。
Android Dalvik Heap 与原生 Java 一样,将堆的内存空间分为三个区域,Young Generation,Old Generation, Permanent Generation。

最近分配的对象会存放在 Young Generation 区域,当这个对象在这个区域停留的时间达到一定程度,它会被移动到 Old Generation,最后累积一定时间再移动到 Permanent Generation 区域。系统会根据内存中不同的内存数据类型分别执行不同的 gc 操作。
GC 发生的时候,所有的线程都是会被暂停的。执行 GC 所占用的时间和它发生在哪一个 Generation 也有关系,Young Generation 中的每次 GC 操作时间是最短的,Old Generation 其次,Permanent Generation 最长。
GC 时会导致线程暂停,导致卡顿,Google 在新版本的 Android 中优化了这个问题, 在 ART 中对 GC 过程做了优化揭秘 ART 细节 —— Garbage collection[5],据说内存分配的效率提高了 10 倍,GC 的效率提高了 2-3 倍(可见原来效率有多低),不过主要还是优化中断和阻塞的时间,频繁的 GC 还是会导致卡顿。
上面就是 Android 系统内存分配和回收相关知识,回过头来看,现在各种手机厂商鼓吹人工智能手机,号称 18 个月不卡顿,越用越快,其实很大一部分 Android 系统的内存优化有关,无非就是利用一些比较成熟的基于统计,机器学习的算法定时清理数据,清理内存,甚至提前加载数据到内存。
返回列表