Android运行时ART和Dalvik虚拟机使用分页和内存映射(mmapping)管理内存。这意味着所有被修改过的内存——无论是通过分配新的对象还是触摸被映射的页——仍然驻留在RAM中并且不能移除分页。唯一从应用中释放内存的方法是释放应用持有的对象引用,让内存能够被垃圾收集器使用。但有一个例外:如果系统想在其它地方使用内存,那么所有被映射但没有被修改的文件,比如代码,可能会被从RAM的分页中移除。
本文将阐述Android如何管理应用进程和内存分配。更多关于如何更有效管理应用内存的信息,请查阅【管理应用的内存】。
垃圾收集
一个被管理的内存环境, 像ART或Dalvik虚拟机,保持追踪每一块内存分配。一旦虚拟机确定某块内存不再被程序使用,它会释放该内存回到堆中,而不需要程序员的任何干预。这个在被管理的内存环境中回收不再被使用的内存的机制被称为垃圾收集。垃圾收集有两个目标:找到程序中在未来不会再被访问的数据对象;以及回收被那些对象使用的资源。
Android的内存堆是一个分代的内存堆,这意味着,基于被分配的对象的预期寿命和大小,它追踪着不同的分配群组。例如,最近被分配的对象属于年轻代。当一个对象保持活跃了足够长的时间,它可能会被提升到老年代,后面还有一个永久代。
每一个堆分代都有它自己的对象可以占据的特定的内存数量上限。任何时候某代开始填充时,系统会执行一个垃圾回收事件来尝试释放内存。这个垃圾收集的持续时长取决于它所收集的对象在哪个代,以及在每个代中有多少活跃对象。
虽然垃圾收集可能非常快,但它仍然会影响您应用的性能。通常您无法掌控代码中垃圾收集事件何时会发生。系统有一套正在运行的标准来决定何时执行垃圾收集。当满足标准时,系统会停止执行进程并开始垃圾收集。如果垃圾收集发生在一个密集的正在处理的循环(如动画或音乐回放期间)中间时,这可能会增加处理时间。这个增加可能潜在地推动应用中代码执行时间超过为有效和平滑帧渲染而建议的16ms阈值。
除此之外,您的代码流可能执行某些类型的工作:这类工作强迫垃圾收集事件更频繁地发生或者使它们延续得比平常时间更长。例如,如果在透明度混合动画的每一帧期间,您在一个for循环最里面部分分配多个对象,可能导致大量对象污染内存堆。在那种环境下,垃圾收集器会执行多个垃圾收集事件并会降低应用的性能。
更多关于垃圾收集的分代信息,请查阅【垃圾收集】。