概览
Android内存管理预研
Android ART和Dalvik虚拟机采用内存分页和内存映射方式管理内存。
垃圾回收
垃圾回收机制的目标:
- 找到不再被引用的的数据对象;
- 声明回收不被引用对象占用的资源;
Android对内存是分代管理的,即基于所分配对象的生命周期,大小进行不同的划分。比如,最新分配内存的对象属于新生代。在相当的时间之后,原来被分配内存的对象会被划分到老生代,然后就是永久代。
每个分代均由自己可占用空间的上限,当一个分代快被充满时,系统就会执行垃圾回收操作。
执行各种操作的代码流程也会促使垃圾回收操作频繁发生或者使回收操作持续更长时间。
内存共享
为了适应所有的需要,Android尝试在各进程之间共享内存。
- 每个APP进程均是从Zygote进程中创建。Zygote进程在系统系统时创建启动,并加载Framework代码及资源,这样分配给framework的内存分页可以最大程度的为各APP进程公用;
- 多数静态数据会被映射到一个进程中。这个技术不仅可以使数据在不同的进程之间共享,还可以在需要的时候将数据换出。
- 很多地方,Android明确了可共享的内存区域给进程之间进行共享。
限制内存
为维持多任务功能的运行,Android为每个APP的堆大小设置了一个硬性上限。
要在一个设备上查看确切可用的堆内存空间大小,可使用getMemoryClass()来查询系统当前APP可用的堆大小。
切换APP
在APP首次启动是,process会被创建,当离开APP时,process会被缓存起来。从而在下次进入到APP时,速度会更快。
但当缓存的processes影响到整体性能时,例如系统的内存low时,会开始kill缓存的进程。
进程间内存分配
Android的运行是以内存空余即浪费内存为前提。因此Android运行中使用所有可获取的空闲内存,也造成了在实际运行App时只使用了较少的内存。
内存类型

- RAM: 速度快,但是大小限制;
- zRAM: RAM一部分,用以交换空间。放入zRAM空间的内容均会被压缩,在交换出zRAM内存时会被间压缩。这部分RAM在内存分页移入或移出zRAM内存时会增长或缩减。设备厂商可以设置最大值。
- Storage: 这部分内存保存了持久化数据,包含了文件系统,App的目标代码,库及平台。这部分内存比另外两个类型额RAM具有更大的容量。
内存分页
RAM内存是分页管理的,每个分页大小经典值是4K大小。
RAM内存的状态只有free和used。使用状态的分页即系统正在占用的内存,可以分为两组:
- 缓存页:存储中文件支持的内存。
- 私有页:进程不同享
- 净页:存储中未经修改的文件副本。
- 脏页:存储中经过修改的文件副本。
- 共享页:进程间共享
- 私有页:进程不同享
- 匿名页:没有存储中文件支持的内存。
内存不足管理
Android的内存不足管理与两种机制:内存交换守护进程和终止程序守护进程。
内存交换守护进程
内存交换守护进程(kswapd)是linux内核的一部分,可以将已用内存转换为可用内存。Linux内核中持有空闲内存的上限和下限阀值,当可用内存低于下限阀值时,kswapd开始回收内存。一旦可用内存高于上限阀值时,kswapd停止回收内存。
kswapd删除干净页来回收内存,因为他们由存储支持切每未被修改。若有进程想要处理被删除的干净页,系统会将分页拷贝进RAM,这个操作叫“请求分页”。

kswapd可将缓存的私有的脏页匿名脏页移入到zRAM进行压缩。这样做可以增加RAM的可用大小。若有继承需要处理zRAM中的脏页,分页会被间压缩并移回RAM中。当与压缩分页关联的进程被杀掉后,分页也会在zRAM中被删除。

但当可用内存低于一个确定值后,系统就开始查杀进程。
终止程序守护进程
很多情况下,kswapd守护进程无法交换处足够的内存。在这种情况下,系统会使用onTrimMemory()通知APP内存不足并且将较少内存分配。若还无法满足APP运行,系统将开始kill进程来获取更多内存。
这个kill程序就是low-memory killer(LKM)终止程序守护进程。
LKM使用"out of memory"的分数来处理,分数高的进程被优先查杀。 后台apps首先被查杀,系统进程被最后查杀。

厂商可以改变LMK的行为。

本文详细解析了Android的内存管理机制,包括ART和Dalvik虚拟机的内存分页与映射,垃圾回收策略,内存共享技术,以及内存限制、切换和分配原则。探讨了内存类型如RAM、zRAM和Storage的特性,以及内存分页管理,同时介绍了内存不足时的管理和应对策略。
897

被折叠的 条评论
为什么被折叠?



