

Android使用虚拟内存和分页,不支持交换程序员
垃圾收集
不管是ART仍是Dalvik虚拟机,都和众多Java虚拟机同样,属于一种托管内存环境(程序员不须要显示的管理内存的分配与回收,交由系统自动管理)。托管内存环境会跟踪每一个内存分配, 一旦肯定程序再也不使用一块内存,它就会将其释放回堆中,而无需程序员的任何干预。回收托管内存环境中未使用内存的机制称为垃圾回收。web
垃圾收集有两个目标:缓存
在程序中查找未来没法访问的数据对象;安全
回收这些对象使用的资源。微信
Android的垃圾收集器不带压缩整理功能(Compact),即不会对Heap作碎片整理。app
Android的内存堆是分代式(Generational)的,意味着它会将全部分配的对象进行分代,而后分代跟踪这些对象。例如,最近分配的对象属于年轻代(Young Generation)。当一个对象长时间保持活动状态时,它能够被提高为年老代(Older Generation),以后还能进一步提高为永久代(Permanent Generation)。编辑器
每一代的对象可占用的内存总量都有其专用上限。每当一代开始填满时,系统就会执行垃圾收集事件以试图释放内存。垃圾收集的持续时间取决于它在收集哪一代的对象以及每一代中有多少活动对象。ide
虽然垃圾收集速度很是快,但它仍然会影响应用程序的性能。一般状况下你不须要控制代码中什么时候执行垃圾收集事件。系统有一组用于肯定什么时候执行垃圾收集的标准。知足条件后,系统将中止执行当前进程并开始垃圾回收。若是在像动画或音乐播放这样的密集处理循环中发生垃圾收集,则会增长处理时间。这种增长可能会致使你的应用程序中的代码执行超过建议的16ms阈值。性能
为实现高效,流畅的帧渲染,Android建议绘制一帧的时间不要超过16ms。flex
此外,你的代码可能会执行各类工做,这些工做会致使垃圾收集事件更频繁地发生,或使其持续时间超过正常范围。例如,若是在Alpha混合动画的每一个帧期间在for循环的最内部分配多个对象,则大量的对象就会污染内存堆。此时,垃圾收集器会执行多个垃圾收集事件,并可能下降应用程序的性能。
共享内存
Android能够跨进程共享RAM页面(Pages)。它能够经过如下方式实现:
每一个应用程序进程都是从名为Zygote的现有进程分叉(fork)出来的。Zygote进程在系统引导并加载framework代码和资源(例如Activity Themes)时启动。要启动新的应用程序进程,系统会fork Zygote进程,而后在新进程中加载并运行应用程序的代码。这种方法容许在全部应用程序进程中共享大多数的为framework代码和资源分配的RAM页面。
大多数静态数据都被映射到一个进程中。该技术容许在进程之间共享数据,而且还容许在须要时将其Page out。这些静态数据包括:Dalvik代码(经过将其置于预连接的.odex文件中进行直接的memory-mapping),app资源(经过将资源表设计为能够mmap的结构并经过对齐APK的zip条目) 和传统的项目元素,如.so文件中的本地代码。
在许多地方,Android使用显式分配的共享内存区域(使用ashmem或gralloc)在进程间共享相同的动态RAM。例如,Window surface在应用程序和屏幕合成器之间使用共享内存,而游标缓冲区在Content Provider和客户端之间使用共享内存。
分配和回收应用的内存
Android为每一个进程分配内存的时候,采用了弹性分配方式,也就是刚开始并不会一下分配不少内存给每一个进程,而是给每个进程分配一个“够用”的虚拟内存范围。这个范围是根据每个设备实际的物理内存大小来决定的,而且能够随着应用后续需求而增长,但最多也只能达到系统为每一个应用定义的上限。
堆的逻辑大小与其使用的物理内存总量并不彻底相同。在检查应用程序的堆时,Android会计算一个名为“比例集大小”(PSS)的值,该值会考虑与其余进程共享的脏页面和干净页面,但其总量与共享该RAM的应用程序数量成正比。此PSS总量就是系统认为是你的物理内存占用量。
Android会在内存中尽可能长时间的保持应用进程,即便有些进程再也不使用了。这样,当用户下次启动应用的时候,只须要恢复当前进程就能够了,不须要从新建立进程,进而减小应用的启动时间。只有当Android系统发现内存不足,而其余为用户提供更紧急服务的进程又须要内存时,Android就会决定关闭某些进程以回收内存。关于这部份内容,稍后再细说。
限制应用的内存
为了维护高效的多任务环境,Android为每一个应用程序设置了堆大小的硬性限制。该限制因设备而异,取决于设备整体可用的RAM。若是应用程序已达到该限制并尝试分配更多内存,则会收到 OutOfMemoryError 。
在某些状况下,你可能但愿查询系统以准确肯定当前设备上可用的堆空间大小,例如,肯定能够安全地保留在缓存中的数据量。你能够经过调用 getMemoryClass() 来查询系统中的这个数字。此方法返回一个整数,指示应用程序堆可用的兆字节数。
切换应用
当用户在应用程序之间切换时,Android会将非前台应用程序(即用户不可见或并无运行诸如音乐播放等前台服务的进程)缓存到一个最近最少使用缓存(LRU Cache)中。例如,当用户首次启动应用程序时,会为其建立一个进程; 可是当用户离开应用程序时,该进程不会退出。系统会缓存该进程。若是用户稍后返回应用程序,系统将从新使用该进程,从而使应用程序切换更快。
若是你的应用程序具备缓存进程而且它保留了当前不须要的内存,那么即便用户未使用它,你的应用程序也会影响系统的总体性能。当系统内存不足时,就会从最近最少使用的进程开始,终止LRU Cache中的进程。另外,系统还会综合考虑保留了最多内存的进程,并可能终止它们以释放RAM。
当系统开始终止LRU Cache中的进程时,它主要是自下而上的。系统还会考虑哪些进程占用更多内存,由于在它被杀时会为系统提供更多内存增益。所以在整个LRU列表中消耗的内存越少,保留在列表中而且可以快速恢复的机会就越大。
夯实基础,关注前沿,娱乐生活
掌握更多前沿技术,获取更多笑点
请关注--------喘口仙氣
本文分享自微信公众号 - 喘口仙氣(gh_db8538619cdd)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。