


本章为官方文档,主要介绍 Android 如何管理应用进程和内存分配。android
首先了解为何要有内存优化,官方的文档介绍程序员
https://developer.android.com/topic/performance/memory-overview?hl=zh-cnweb
Android 运行时 (ART) 和 Dalvik 虚拟机使用分页和内存映射来管理内存。这意味着应用修改的任何内存,不管修改的方式是分配新对象仍是轻触内存映射的页面,都会一直驻留在 RAM 中,而且没法换出。要从应用中释放内存,只能释放应用保留的对象引用,使内存可供垃圾回收器回收。这种状况有一个例外:对于任何未经修改的内存映射文件(如代码),若是系统想要在其余位置使用其内存,可将其从 RAM 中换出。缓存
https://developer.android.com/topic/performance/memory?hl=zh-cn安全
随机存取存储器 (RAM) 在任何软件开发环境中都是一项宝贵资源,但在移动操做系统中,因为物理内存一般都有限,所以 RAM 就更宝贵了。虽然 Android 运行时 (ART) 和 Dalvik 虚拟机都执行例行的垃圾回收任务,但这并不意味着您能够忽略应用分配和释放内存的位置和时间。您仍然须要避免引入内存泄漏问题(一般因在静态成员变量中保留对象引用而引发),并在适当时间(如生命周期回调所定义)释放全部 Reference 对象。微信

Android经过的如下几个方面对内存进行管理:app
垃圾回收框架
垃圾回收编辑器
ART 或 Dalvik 虚拟机之类的受管内存环境会跟踪每次内存分配。一旦肯定程序再也不使用某块内存,它就会将该内存从新释放到堆中,无需程序员进行任何干预。这种回收受管内存环境中的未使用内存的机制称为“垃圾回收”。垃圾回收有两个目标:在程序中查找未来没法访问的数据对象,并回收这些对象使用的资源。ide
Android 的内存堆是分代的,这意味着它会根据分配对象的预期寿命和大小跟踪不一样的分配存储分区。例如,最近分配的对象属于“新生代”。当某个对象保持活动状态达足够长的时间时,可将其提高为较老代,而后是永久代。
堆的每一代对相应对象可占用的内存量都有其自身的专用上限。每当一代开始填满时,系统便会执行垃圾回收事件以释放内存。垃圾回收的持续时间取决于它回收的是哪一代对象以及每一代有多少个活动对象。
尽管垃圾回收速度很是快,但仍会影响应用的性能。一般状况下,您没法从代码中控制什么时候发生垃圾回收事件。系统有一套专门肯定什么时候执行垃圾回收的标准。当条件知足时,系统会中止执行进程并开始垃圾回收。若是在动画或音乐播放等密集型处理循环过程当中发生垃圾回收,则可能会增长处理时间,进而可能会致使应用中的代码执行超出建议的 16ms 阈值,没法实现高效、流畅的帧渲染。
此外,您的代码流执行的各类工做可能迫使垃圾回收事件发生得更频繁或致使其持续时间超过正常范围。例如,若是您在 Alpha 混合动画的每一帧期间,在 for 循环的最内层分配多个对象,则可能会使内存堆受到大量对象的影响。在这种状况下,垃圾回收器会执行多个垃圾回收事件,并可能下降应用的性能。
共享内存
共享内存
为了在 RAM 中容纳所需的一切,Android 会尝试跨进程共享 RAM 页面。它能够经过如下方式实现这一点:
每一个应用进程都从一个名为 Zygote 的现有进程分叉。系统启动并加载通用框架代码和资源(如 Activity 主题背景)时,Zygote 进程随之启动。为启动新的应用进程,系统会分叉 Zygote 进程,而后在新进程中加载并运行应用代码。这种方法使为框架代码和资源分配的大多数 RAM 页面可在全部应用进程之间共享。大多数静态数据会内存映射到一个进程中。这种方法使得数据不只能够在进程之间共享,还能够在须要时换出。静态数据示例包括:Dalvik 代码(经过将其放入预先连接的 .odex 文件中进行直接内存映射)、应用资源(经过将资源表格设计为可内存映射的结构以及经过对齐 APK 的 zip 条目)和传统项目元素(如 .so 文件中的原生代码)。在不少地方,Android 使用明确分配的共享内存区域(经过 ashmem 或 gralloc)在进程间共享同一动态 RAM。例如,窗口 surface 使用在应用和屏幕合成器之间共享的内存,而光标缓冲区则使用在内容提供器和客户端之间共享的内存。
分配与回收应用内存
分配与回收应用内存
Dalvik 堆局限于每一个应用进程的单个虚拟内存范围。这定义了逻辑堆大小,该大小能够根据须要增加,但不能超过系统为每一个应用定义的上限。
堆的逻辑大小与堆使用的物理内存量不一样。在检查应用堆时,Android 会计算按比例分摊的内存大小 (PSS) 值,该值同时考虑与其余进程共享的脏页和干净页,但其数量与共享该 RAM 的应用数量成正比。此 (PSS) 总量是系统认为的物理内存占用量。有关 PSS 的详情,请参阅调查 RAM 使用量指南。
Dalvik 堆不压缩堆的逻辑大小,这意味着 Android 不会对堆进行碎片整理来缩减空间。只有当堆末尾存在未使用的空间时,Android 才能缩减逻辑堆大小。可是,系统仍然能够减小堆使用的物理内存。垃圾回收以后,Dalvik 遍历堆并查找未使用的页面,而后使用 madvise 将这些页面返回给内核。所以,大数据块的配对分配和解除分配应该使全部(或几乎全部)使用的物理内存被回收。可是,从较小分配量中回收内存的效率要低得多,由于用于较小分配量的页面可能仍在与其余还没有释放的数据块共享。
限制应用内存
限制应用内存
为了维持多任务环境的正常运行,Android 会为每一个应用的堆大小设置硬性上限。不一样设备的确切堆大小上限取决于设备的整体可用 RAM 大小。若是您的应用在达到堆容量上限后尝试分配更多内存,则可能会收到 OutOfMemoryError。
在某些状况下,例如,为了肯定在缓存中保存多少数据比较安全,您可能须要查询系统以肯定当前设备上确切可用的堆空间大小。您能够经过调用 getMemoryClass() 向系统查询此数值。此方法返回一个整数,表示应用堆的可用兆字节数。
切换应用
切换应用
当用户在应用之间切换时,Android 会将非前台应用保留在缓存中。非前台应用就是指用户看不到或未运行前台服务(如音乐播放)的应用。例如,当用户首次启动某个应用时,系统会为其建立一个进程;可是当用户离开此应用时,该进程不会退出。系统会将该进程保留在缓存中。若是用户稍后返回该应用,系统就会重复使用该进程,从而加快应用切换速度。
若是您的应用具备缓存的进程且保留了目前不须要的资源,那么即便用户未使用您的应用,它也会影响系统的总体性能。当系统资源(如内存)不足时,它将会终止缓存中的进程。系统还会考虑终止占用最多内存的进程以释放 RAM。
以上内容为官方内容,可从官网查阅:
强调内存释放的重要性而且建议从如下几点优化应用内存使用:
监控可用内存和内存使用量
使用内存效率更高的代码结构
移除会占用大量内存的资源和库
夯实基础,关注前沿,娱乐生活
掌握更多前沿技术,获取更多笑点
请关注--------喘口仙氣
本文分享自微信公众号 - 喘口仙氣(gh_db8538619cdd)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。