- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Android操作系统之内存回收策略由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
Android 是一款基于 Linux 内核,面向移动终端的操作系统。为适应其作为移动平台操作系统的特殊需要,谷歌对其做了特别的设计与优化,使应用程序关闭但不退出,并由操作系统进行进程的回收管理。本文在 Application Framework 与 Linux 内核两个层次上,以进程为粒度,对 Android 操作系统的进程资源回收机制进行了剖析。读者可以从本文获得对 Android 应用程序的生存周期的进一步理解,从而更加合理、高效地构建应用程序.
Android 操作系统中的内存回收可分为两个层次:
1、默认内存回收、即Application Framework 层的默认回收.
2、内核级内存回收.
Linux 内核中的内存回收 lowmemorykiller、OOM_killer.
默认内存回收:(代码可查阅 ActivityManagerService.java类)回收动作入口activityIdleInternal().
Android 系统中内存回收的触发点大致可分为三种情况.
第一,用户程序调用 StartActivity(), 使当前活动的 Activity 被覆盖; 。
第二,用户按 back 键,退出当前应用程序;第三,启动一个新的应用程序.
这些能够触发内存回收的事件最终调用的函数接口就是 activityIdleInternal()。当 ActivityManagerService 接收到异步消息 IDLE_TIMEOUT_MSG 或者 IDLE_NOW_MSG 时,activityIdleInternal() 将会被调用。 IDLE_NOW_MSG 由 Activity 的切换以及 Activiy 焦点的改变等事件引发,IDLE_TIMEOUT_MSG 在 Activity 启动超时的情况下引发,一般这个超时时间设为 10s,如果 10s 之内一个 Activity 依然没有成功启动,那么将发送异步消息 IDLE_TIMEOUT_MSG 进行资源回收。activityIdleInternal() 的主要任务是改变系统中 Activity 的状态信息,并将其添加到不同状态列表中。它的主要工如下:
首先,调用 scheduleAppGcsLocked() 方法通知所有进行中的任务进行垃圾回收。scheduleAppGcsLocked() 将进行调度 JVM 的 garbage collect,回收一部分内存空间,这里仅仅是通知每个进程自行进程垃圾检查并调度回收时间,而非同步回收.
然后,取出 mStoppingActivities 和 mFinishigActivities 列表中的所有内容,暂存在临时变量中。这两个列表分别存储了当前状态为 stop 和 finishi 的 activity 对象。对于 stop 列表,如果其中的 activity 的 finish 状态为 true,判断是不是要立即停止,如果要立即停止则调用 destroyActivityLocked() 通知目标进程调用 onDestroy() 方法,否则,先调用resumeTopActivity() 运行下一个 Activity。如果 finish 状态为 false,则调用 stopActivityLocked() 通知客户进程停止该 Activity,这种情况一般发生在调用 startActivity() 后。对于 finish 列表,直接调用 destroyActivityLocked() 通知客户进程销毁目标 Activity。这里的 destroyActivityLocked 等函数并没有真正意义上改变内存的使用,只是将其状态改变为“允许回收”,真正的回收在下面即将调用的 trimApplications() 函数中.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private
final
void
trimApplications() {
synchronized
(
this
) {
// First remove any unused application processes whose package
// has been removed.
for
(i=mRemovedProcesses.size()-
1
; i>=
0
; i--) {
(
1
)
//kill process;
}
if
(!updateOomAdjLocked()) {
(
2
)
//do something default
}
// Finally, if there are too many activities now running, try to
// finish as many as we can to get back down to the limit.
(
3
)
do
something
}
}
|
(1)当程序执行到 trimApplications() 之后,首先检查 mRemovedProcesses 列表中的进程。mRemovedProcesses 列表中主要包含了 crash 的进程、5 秒内没有响应并被用户选在强制关闭的进程、以及应用开发这调用 killBackgroundProcess 想要杀死的进程。调用 Process.killProcess 将所有此类进程全部杀死.
(2)调用 updateOomAdjLocked() 函数,若成功返回,说明 Linux 内核支持 setOomAdj() 接口,updateOomAdjLocked 将修改 adj 的值并通知 linux 内核,内核根据 adj 值以及内存使用情况动态管理进程资源(lowmemorykiller 和 oom_killer)。若 updateOomAdjLocked() 返回为假,则表示当前系统不支持 setOomAdj() 接口,将在本地进行默认的资源回收.
(3)最后,如果当前依然运行了过多的 Activity,对多余的 Activity 进行回收。 trimApplications() 的大多数的代码都在处理 Oom_killer 不存在情况下的默认资源回收,下面对其默认回收过程(即代码中标记(2)的位置)进行进一步分析。其回收过程可大致描述如下.
步骤一,获取当前所有运行的进程 mLruProcesses,mLruProcesses 中的排序规则是按最近使用时间。对 mLruProcesses 中不能被关闭的进程进行计数,这些不能被关闭的进程包括运行 service 的进程,运行broadcast receiver 的进程等.
步骤二, 设当前最大运行进程数 curMaxProcs = curMaxProcs + numServiceProcs(即默认最大进程数与运行 Service 的进程数之和),如果当前进程的数量 mRemovedProcesses.size() 大于这个值,则遍历所有当前运行的进程,杀死符合条件的那些进程并释放内存。进程被杀死的条件是:必须是非 persistent 进程,即非系统进程,必须是空进程,即进程中没有任何 activity 存在。如果杀死存在 Activity 的进程,有可能关闭用户正在使用的程序,或者使应用程序恢复的时延变大,从而影响用户体验;必须无 broadcast receiver。运行 broadcast receiver 一般都在等待一个事件的发生,用户并不希望此类程序被系统强制关闭;进程中 service 的数量必须为 0。存在 service 的进程很有可能在为一个或者多个程序提供某种服务,如 GPS 定位服务。杀死此类进程将使其他进程无法正常服务.
步骤三,再次检查当前运行的进程,如果 mRemovedProcesses.size() 仍然大于 curMaxProcs,则放宽条件再次进行回收.
步骤四,上面 3 个过程都是针对整个 process 进行的资源回收。在以上过程执行完毕之后,将在更小的粒度上对 Activity 的资源进行回收。与上面所述类似,列表 mLRUActivities 存储了当前所有运行中的 Activity,排序规则同样为最少访问原则。mLRUActivities.size() 返回系统中运行的 Activity 的数量,当其大于 MAX_ACTIVITIES(MAX_ACTIVITIES 是一个常量,一般值为 20,代表系统中最大允许同时存在的 Activity)时。将回收部分满足条件的 Activity 以减少内存的使用。 这里回收的只是 Activity 的内存资源,并不会杀死进程,也不会影响进程的运行。当进程需要调用被杀掉的 Activity 时,可以从保存的状态中回复,当然可能需要相对长一点的时延.
Linux 内核中的内存回收 。
lowmemorykiller 。
trimApplications() 函数中会执行一个叫做 updateOomAdjLocked() 的函数,如果返回 false,则执行默认回收,若返回 true 则不执行默认内存回收。 updateOomAdjLocked 将针对每一个进程更新一个名为 adj 的变量,并将其告知 Linux 内核,内核维护一个包含 adj 的数据结构(即进程表),并通过 lowmemorykiller 检查系统内存的使用情况,在内存不足的情况下杀死一些进程并释放内存.
由于 Android 操作系统中的所有应用程序都运行在独立的 Dalvik 虚拟机环境中,Linux 内核无法获知每个进程的运行状态,也就无法为每个进程维护一个合适的 adj 值,因此,Android Application Framework 中必须提供一套机制以动态的更新每个进程的 adj。这就是 updateOomAdjLocked().
Android 基于进程中运行的组件及其状态规定了默认的五个回收优先级:
IMPORTANCE_FOREGROUND: IMPORTANCE_VISIBLE: IMPORTANCE_SERVICE: IMPORTANCE_BACKGROUND: IMPORTANCE_EMPTY
最后此篇关于Android操作系统之内存回收策略的文章就讲到这里了,如果你想了解更多关于Android操作系统之内存回收策略的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
作者:小林coding 计算机八股文网站:https://xiaolincoding.com 大家好,我是小林。 今天跟大家聊聊,常见的缓存更新策略。 Cache Aside(旁路缓存)策略; Rea
我使用 git 多年,最近为了一个项目改用 mercurial。在过去的 6 个月里,我已经学会了如何通过命令行很好地使用 Mercurial。 这可能是我的想象,但在我看来,mercurial 在
这个问题适合任何熟悉的人 Node.js express Passport 带有 Passport 的 JWT 身份验证(JSON Web token ) Facebook OAuth2.0 或谷歌
在 Coq 中,当试图证明记录的相等性时,是否有一种策略可以将其分解为所有字段的相等性?例如, Record R := {x:nat;y:nat}. Variables a b c d : nat.
我正在处理的项目目前只有一个 Bootstrap 文件,用于初始化应用程序中的所有 javascript 对象。类似于下面的代码 if(document.getElementById('nav'))
我正在考虑使用 OpenLDAP 在首次登录时添加密码到期和强制更改密码。 似乎使用 ppolicy 覆盖来实现这一点。 当我在 ppolicy.schema 中看到这个时,我开始使用 ppolicy
这基本上是我昨天问的一个问题的重新陈述,因为我得到的一个答案似乎没有理解我的问题,所以我一定是不清楚。我的错。 因为 WPF 依赖于 DirectX,所以它对卡和驱动程序的内部非常敏感。我有一个案例,
我是单点登录(SSO)概念的新手。我开始知道 SAML 请求和响应是实现 SSO 流程的最佳方式。然后我开始阅读有关 SAML2.0 的信息。我来了一个术语 NameIdPolicy 在 saml1.
关闭。这个问题需要更多 focused .它目前不接受答案。 想改进这个问题?更新问题,使其仅关注一个问题 editing this post . 5年前关闭。 Improve this questi
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 9 年前。 Improv
在 Azure 上创建新的 SQL 数据库时,它将“计算+存储”选项设置为“2 vCore + 32GB 数据最大大小”作为默认配置,但我不想使用 vCore,我可以更改它。但问题是,是否可以通过策略
我希望创建一项策略,防止在未启用身份验证的情况下创建应用服务(仅审核它们是不够的)。 以下策略可以正确识别未启用身份验证的现有资源: { "mode": "All", "policyRule"
我正在尝试从现有 AuditIfNotExists 策略创建 DeployIfNotExists 策略。部署时不会出错,但会错误提示“没有相关资源与策略定义中的效果详细信息匹配”。当评估政策时。当我将
我正在尝试从现有 AuditIfNotExists 策略创建 DeployIfNotExists 策略。部署时不会出错,但会错误提示“没有相关资源与策略定义中的效果详细信息匹配”。当评估政策时。当我将
我正在使用 wunderground 的 json api 来查询我网站上的天气状况。 api 为我提供了一个包含所有必要数据的漂亮 json 对象,但我每天只能进行多次调用。存储这些数据的首选方式是
我有一个名为可视化数据结构的项目。我有这样的 OOP 设计。 Class VisualDataStructures extends JFrame Class ControlPanel extends
这个问题在这里已经有了答案: 关闭 14 年前。 副本: Use javascript to inject script references as needed? Javascript 没有任何指
Android 应用程序遇到了一些 ANR 问题,因此我实现了 StrictMode 策略。以前从未使用过这个,所以希望有人可以帮助解释以下内容: 为什么日志显示 2 个看似相似的违规行为,除了前 4
我目前正在尝试解决一个问题。假设我们在路上行驶,我们知道路上有 10 家酒店。每家酒店都有 0 到 6 星。我的问题是:找到选择星级酒店的最佳解决方案。唯一的问题是:您不能回头去参观您已经决定不去的酒
我正在将我的应用程序迁移到 MVP。从这个 konmik 中获得了有关静态演示者模式的提示 这是我的简要 MVP 策略。为简洁起见,删除了大部分样板和 MVP 监听器。这个策略帮助我改变了方向,证明了
我是一名优秀的程序员,十分优秀!