您的位置:首页 > 移动开发 > Android开发

[Android 性能优化系列]内存之基础篇--Android如何管理内存

2016-03-03 11:35 387 查看
原文地址:http://developer.android.com/training/articles/memory.html

随机访问存储器(Ram) 不管在哪种软件开发环境中都是一种极其宝贵的资源,而在移动开发平台下,极其有限的物理内存则更为宝贵。因此,虽然Android的Dalvik虚拟机会执行垃圾回收,但这不代表你可以对你应用的内存分配和释放不闻不问。

为了使垃圾回收期能够回收你应用中的内存,你需要避免内存泄露(通常是由于在全局变量持有某个对象引起的),以及在适当的时候释放点引用对象(比如在生命周期中)。对于大多数应用而言,Dalvik虚拟机的垃圾回收器会帮你回收掉那些不再处于作用域中的对象的内存。

本文将介绍 Android 是如何管理内存进程以及内存分配,以及如何在开发过程中减少内存使用。如果对于 Java 的清理资源机制,你还希望了解的更多,那么你可以去看看一些关于资源引用的书籍或者在线文档。如果你正在寻找如何分析当前应用内存使用的资料,那么你可以参考这篇文章(Investingating
Your RAM Usage)。

Android 如何管理内存

Android 虽然没有提供内存的交换空间,但是他使用了分页和内存映射文件来管理内存。这代表任何你修改过的内存,不论是分配了一个新的对象,再或者是更改了内存映射夜的操作,都将在保留在内存,以至于不能被释放。从你的应用中释放这些内存唯一的方法就是将使用的对象释放,使得垃圾回收机制能够能够回收他。唯一的例外是,对于那些没有被更改的数据,例如代码,当系统希望在别的地方使用他的时候,就被系统调用到哪里。

公有内存

Android 为了在RAM中能够存放尽量多的资源,因此他允许某些共有内存跨进程使用。他的原理如下:

1.每一个应用进程都是被一个叫做 Zygote 的进程负责出来的。Zygote 进程是在系统启动的时候自动启动的,并且内部加载了很多公用框架代码以及资源(例如 Activity 主题等)。启动一个新应用的时候,系统从
Zygote 进程中复制这些资源,然后在新进程中运行应用代码。这就允许框架和资源中的大量内存资源被跨进程复用。

2.大多数静态数据是通过内存映射放置到进程中。这不仅代表着同样的数据能够被跨进程分享,同样代表着当需要的时候能够随时被调用。举个例子,静态数据包括:Dalvik 码(使用预编译的.odex来直接调用),应用资源(国通简历资源映射表来调用),以及一些默认的项目资源,例如在.so 文件中的本地代码

3.在很多地方,Android 都会通过直接分配内存区域来跨进程分享同样的动态 RAM。例如,窗口 Surface 使用公用内存在应用和屏幕排序,Cursor 缓存在 ContentProvider 和客户端之间使用同样的内存

由于公用内存的使用,我们需要关心你的应用需要使用多少内存。 如何正确分析应用内存使用请参看Investingating Your RAM
Usage。

分配和释放应用内存

以下是关于 Android 如何分配和释放内存的部分:

1.每个进程的Dalvik 堆会被限制在一个虚拟内存范围内。这代表着逻辑堆的大小可以随着他的需要而增长(当然系统会限制每个应用的最大内存占用)

2.每个堆的逻辑大小和堆使用的物理内存并不是一样。当检查应用的堆的时候,Android 会计算一个叫做比例大小(PPS)的值,这会将与其他应用共享的脏数据和清洁数据都计算在内,你的PPS的总值将被系统认为是物理内存的值。更详细的信息请查看Investingating
Your RAM Usage。

3.Dalvik堆并不会压缩堆的逻辑尺寸,这代表着Android并不会通过清理空间来减小堆得大小。Android只在堆没有剩余空间的时候才对堆本身采取回收措施。但这并不代表被堆使用的物理内存可以得到释放。在垃圾回收之后,Dalvik会扫描堆来找到不用的内存页,并通过madvise将这些内存页释放到内核空间。因此大批量的分配或者释放对象将会回收使用过的物理内存。尽管如此,从那些小的资源中回收内存空间效果并不是很好,因为存放这些小资源的分页,很可能被其他对象所使用,导致不能释放。

限制应用内存

Android为了保证自身的多任务环境,他为每一个应用设置了堆的硬件限制。这个限制取决于设备拥有多少RAM。如果你的应用已经达到了堆的上限,并且还希望分配更多的内存空间,那么就会导致OOM。

在某种条件下,你或许希望知道在当前设备上系统最大允许的堆空间,打个比方说用来决定缓存的大小。那么你可以通过查询getMemoryClass()来获取到这些系统数据,他会将你应用可用的内存作为一个int类型的值进行返回,这将会在下面被讨论。

切换应用

当用户在应用之间进行切换时,Android使用近期最少使用算法(LRU)将进程保存在一个前台应用组件列表中,而非存放在交换空间。比如说当用户首次启动一个应用的时候,该应用的进程就会被创建,但是当用户离开这个应用的时候,应用却没有完全退出。系统将保存进程的缓存,这样一来当用户接下来返回到当前应用的时候,这个缓存就可以被尽可能快的调用,以提升进入程序的速度。

如果你的应用有一个缓存的进程,并且他保持了他所需要的内存,那么即使在用户没有使用到他的时候,也会限制系统的整体性能。因此当系统内存资源不足的时候,他就可能会杀死那些最近没有被使用到的进程。所以为了使自己进程能够尽可能的保持,最好跟着下面的章节学习,将自己的资源进行释放

如果希望了解更多关于进程在非前台环境下是如何被缓存,以及Android如何决定哪个进程被杀死的信息,那么请参看进程与线程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: