Android 最佳性能实践之内存管理(一)

经常在网上看到一些大神分享不少关于内存优化方面的建议,受益匪浅,打算从官方的文档学习一下内存管理的知识,自己翻译提升印象的同时分享给其他开发的小伙伴,希望能一起进步,有翻译或者理解不对的地方欢迎指正。原文地址: https://developer.android.com/training/articles/memory.html

RAM在所有的操作系统中都是稀缺资源,在手机中因为物理内存受到限制,这个问题还要严重得多。虽然Dalvik虚拟机负责垃圾回收,但是你不能因此而忽略内存的分配释放问题。

为了垃圾回收器可以从你应用中回收内存,你应该避免内存泄漏(通常由于全局成员引用了一个对象引起),在合适的时间释放对对象的引用(在生命周期回调中)。对于大多数应用来说,垃圾回收器负责:当对象离开了它的作用域时,系统就回收分配给它们的内存。

这篇文章解释了,安卓系统如何管理app的进程和内存分配释放和我们如何在开发应用中减少对内存的使用。更多关于使用JAVA清理资源的信息,我们可以参考其他书或者在线文档资源。如果你正在寻找如何分析自己app中已分配内存的方法,建议阅读read Investigating Your RAM Usage.送上地址:https://developer.android.com/studio/profile/investigate-ram.html


安卓如何管理内存

安卓没有给内存提供交换空间,它使用页、内存映射来管理内存。这意味着任何修改内存-无论是分配新对象,还是映射表,都会在RAM内存中常驻无法移除。所以唯一释放内存的方式就是移除对象的引用,这样垃圾回收器就可以释放内存了。这可能发生一个异常:任何在映射表中却没有修改的文件,比如代码,都可能被从RAM中移除。

共享内存

为了让RAM可以处理所有的事,安卓系统在进程间共享RAM它通过下面的方法实现:

  • 每个应用进程都是从一个Zygote进程中分支fork出来的。当系统开始运行,加载通用框架代码和资源(比如activity主题)时,Zygote进程开始工作。为了开启一个新的应用进程, 系统fork Zygote进程产生一个新的进程,然后加载并运行代码。这就使得大多数的RAM 页被用来分配给framework的代码,同时促使RAM资源能够在应用的所有进程之间进行共享。

  • 大多数static数据被映射到一个进程中。这不仅使得同样的数据能够在进程间共享,也能在有需要的时候被释放。常见的static数据:Dalvik虚拟机代码,应用资源和.so文件等。

  • 在多数情况下,安卓通过显式分配内存区域(例如ashmem和gralloc)在进程之间共享动态RAM资源。比如,Window Surface在App与Screen Compositor之间使用共享的内存,cursor buffers在content provider和客户端之间共享内存。

分配和回收内存

安卓如何分配和回收内存:

  • Dalvik虚拟机分配给每个进程的heap堆内存被限制在虚拟内存范围内。这定义了逻辑的堆内存的大小,根据需要这个大小会自增长(但每个应用最多只能增长到一个上限)。

  • 逻辑上的堆内存大小和实际物理上使用的内存大小是不一样的。当检查应用的堆栈时,安卓会计算一个称为Proportional Set Size(PSS)的值,记录了应用程序自身占用以及与其他进程进行共享的内存。这个PSS值的总大小才被系统认为是物理内存的大小。更多关于PSS的信息,请查看Investigating Your RAM Usage。

  • Dalvik 不会对堆内存中的空闲内存做内存整理。只有在Heap的尾部有没有足够的内存空间时,才会触发垃圾释放GC。GC后,Dalvik 会检查Heap,找到无用的页,通过madvise函数把它们返回给内核。因此,成对申请和释放大片内存会导致所有使用过的物理内存被回收。然而,回收小块内存可能效率更差,因为小块内存使用的页可能仍被还没释放的对象占用,导致该page无法回收。

限制应用内存

为了维持多任务处理环境,安卓系统对每个应用的heap大小都进行了严格的限制。这个数值随着设备变化而变化,具体要看设备可用的RAM空间有多少。一旦你的应用占用的内存接近了堆栈上限,却仍申请更多内存,你将收到OOM错误提示。

你可以通过调用getMemoryClass()方法得到应用可用的堆栈大小。这将会在下面的篇幅讨论,详见Check how much memory you should use.

应用间的切换

当用户切换应用时,安卓并不会交换内存空间,而是把非前台进程放到LRU缓存中。例如,当用户第一次启动一个应用时,系统会为它开启一个进程。但是当用户离开这个应用时,进程不会立即被销毁,而是被缓存到系统中,因此到用户返回应用时,进程会reused,以便加快应用切换。

如果你的应用有一个被缓存的进程,这个被缓存的进程也会占用一定的内存,即便用户不再使用你的应用,它会对系统的整体性能有影响。因此,当系统内存不足,它会杀掉LRU缓存中最近没用过的进程,但也会考虑优先杀死占用内存最多的进程。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值