final ArrayList<ProcessRecord> mLruProcesses = new ArrayList<ProcessRecord>();
在AMS的内部属性中使用mLruProcesses集合保存所有的进程信息,AMS将所有进程按照优先级从低到高的顺序保存着对应的ProcessRecord信息,即排在前面的进程优先级越低,当系统内存不足时优先被Killer杀死;
在AMS的工作过程中,会不断调用updateLruProcessLocked()方法进行进程排序,在mLruProcesses()中保存按照以下规则保存数据
在AMS中越重要的进程会放在mLruProcesses集合的最后面,正在使用交互的进程会保存在最后,然后按照其他进程、Service进程、Activity进程的顺序重要行逐步增加,Activity进程的重要性最高,为了区分各个进程的位置,AMS中引入mLruProcessServiceStart和mLruProcessActivityStart变量保存二者的起始位置,在添加时当进程中包含活动则添加到mLruProcessActivityStart之后,如果不包含活动但包含Service服务,则添加到mLruProcessServiceStart之后;
final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
ProcessRecord client) {
final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
|| app.treatLikeActivity || app.recentTasks.size() > 0;//1、
final boolean hasService = false;
if (!activityChange && hasActivity) { // 如果activityChange为false则无需改变位置
return;
}
mLruSeq++; // 更新编号
final long now = SystemClock.uptimeMillis();
app.lastActivityTime = now; // 保存更新的时间
if (hasActivity) { // 如果包含Activity,
final int N = mLruProcesses.size();
if (N > 0 && mLruProcesses.get(N-1) == app) {
return;
}
} else {
if (mLruProcessServiceStart > 0 // 不包含Activit但已经存在其他段的最末尾,也无需更新
&& mLruProcesses.get(mLruProcessServiceStart-1) == app) {
return;
}
}
int lrui = mLruProcesses.lastIndexOf(app); // 获取目前位置的index
if (app.persistent && lrui >= 0) {
return;
}
if (lrui >= 0) {
if (lrui < mLruProcessActivityStart) { // 如果index小于mLruProcessActivityStart,则Activity段前移一位
mLruProcessActivityStart--;
}
if (lrui < mLruProcessServiceStart) {//如果index小于mLruProcessServiceStart,则Activity段前移一位
mLruProcessServiceStart--;
}
mLruProcesses.remove(lrui); //移除原来的app信息
}
int nextIndex; //
if (hasActivity) {
final int N = mLruProcesses.size();
if ((app.activities.size() == 0 || app.recentTasks.size() > 0)
&& mLruProcessActivityStart < (N - 1)) {
mLruProcesses.add(N - 1, app); // 如果进程不存在活动,但recentTasks存在任务则添加到最后位置
final int uid = app.info.uid;
for (int i = N - 2; i > mLruProcessActivityStart; i--) {
ProcessRecord subProc = mLruProcesses.get(i);
if (subProc.info.uid == uid) { // 遍历集合中进程,匹配uid相等的进程
if (mLruProcesses.get(i - 1).info.uid != uid) {//处理其他进程,将该用户进程前移,其他进程后移
ProcessRecord tmp = mLruProcesses.get(i);
mLruProcesses.set(i, mLruProcesses.get(i - 1));
mLruProcesses.set(i - 1, tmp);
i--;
}
} else {
break;
}
}
} else {
mLruProcesses.add(app); // 直接添加进程信息
}
nextIndex = mLruProcessServiceStart;
} else if (hasService) { 存在Service服务
mLruProcesses.add(mLruProcessActivityStart, app); // 保存在Service服务的开始位置
nextIndex = mLruProcessServiceStart;
mLruProcessActivityStart++; // mLruProcessActivityStart后移
} else {
int index = mLruProcessServiceStart;
if (client != null) {
int clientIndex = mLruProcesses.lastIndexOf(client);//获取当前客户端最高级的位置
if (clientIndex <= lrui) {
clientIndex = lrui; // 如果最高级小则赋值最高级为lrui
}
if (clientIndex >= 0 && index > clientIndex) {
index = clientIndex;
}
}
mLruProcesses.add(index, app); // 保存在头部位置
nextIndex = index-1;
mLruProcessActivityStart++;
mLruProcessServiceStart++;
}
for (int j=app.connections.size()-1; j>=0; j--) {
ConnectionRecord cr = app.connections.valueAt(j);
if (cr.binding != null && !cr.serviceDead && cr.binding.service != null
&& cr.binding.service.app != null
&& cr.binding.service.app.lruSeq != mLruSeq
&& !cr.binding.service.app.persistent) {
nextIndex = updateLruProcessInternalLocked(cr.binding.service.app, now, nextIndex,
"service connection", cr, app);
}
}
for (int j=app.conProviders.size()-1; j>=0; j--) {
ContentProviderRecord cpr = app.conProviders.get(j).provider;
if (cpr.proc != null && cpr.proc.lruSeq != mLruSeq && !cpr.proc.persistent) {
nextIndex = updateLruProcessInternalLocked(cpr.proc, now, nextIndex,
"provider reference", cpr, app);
}
}
}
在updateLruProcessLocked()中主要执行流程:
关于AMS中进程的管理就分析结束了,简单来说就是AMS会自动更新集合中进程 的位置,从而区分进程的区域和优先级部分,下面一起看下Android 中的进程管理机制;
Android的内存管理实际是通过与Linux协作完成的,Linux通过OOM KIller机制通知Android端执行内存释放操作,关于OOM机制主要包含以下特点:
在AMS执行过程中会不断的更新进程的优先级,主要体现是根据进程条件设置进程中对应的adj信息,然后将赋值的adj更新到OOM机制中改变进程的等级信息,Android中区分进程的原则
在前面的ActivityManagerService的内存管理分析知道,程序在activityIdleInternalLocked()的最后调用了trimApplications()执行进程的管理
final void trimApplicationsLocked() {
for (i=mRemovedProcesses.size()-1; i>=0; i--) { // 1、删除mRemoveProcess进程中的数据
12210 final ProcessRecord app = mRemovedProcesses.get(i); // 获取进程app
12211 if (app.activities.size() == 0&& app.curReceiver == null && app.services.size() == 0) {//确定进程为空
12218 if (app.pid > 0 && app.pid != MY_PID) {
12219 app.kill("empty", false); // 直接杀死进程
12220 } else {
12222 app.thread.scheduleExit(); // 执行进程退出
12226 }
12227 cleanUpApplicationRecordLocked(app, false, -1);
12228 mRemovedProcesses.remove(i); // 移除进程信息
12235 }
12236 }
updateOomAdjLocked() //2、为所有的进程更新 oom adj 的值
}
trimApplications()中直接调用 trimApplicationsLocked()方法,执行删除mRemovedProcesses集合中保存的进程,mRemovedProcesses主要保存即将被清除的进程,一般mRemoveProcess集合中数据来源:
程序遍历mRemovedProcesses集合中的进程信息,然后判断当前进程是否为空进程,然后分别执行进程杀死和进程退出操作,最后从集合中清除进程信息,在清除mRemovedProcesses中进程后,调用updateOomAdjLocked()判断系统是否支持OOM Killer,并更新所有进程的优先级和管理进程,在查看源码之前先介绍下ProcessRecord类
curAdj:进程当前的adj值,反应了进程的优先级
setAdj:上一个设置的adj的值
curRawAdj:第一次对app评级后计算的adj的值,
setRawAdj:删一个curRawAdj设置的值
maxAdj:OOM的最大调整值
updateOomAdjLocked()第二部分,主要计算每个进程的优先级,即oom_adj的值,如果底层Linux包含OOM Killer返回true,否则返回false;
final void updateOomAdjLocked() {
final ActivityRecord TOP_ACT = resumedAppLocked(); // 1、获取最顶部的resume的ActivityRecord对象
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;// 2、获取顶部活动所在的进程
final int N = mLruProcesses.size();
for (int i=mActiveUids.size()-1; i>=0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
uidRec.reset(); // 复位所有的UidRecord对象,UidRecord主要保存每个用户的最高优先级进程
}
final int emptyProcessLimit = mConstants.CUR_MAX_EMPTY_PROCESSES; //获取允许空进程的数量,此处返回16
final int cachedProcessLimit = mConstants.CUR_MAX_CACHED_PROCESSES - emptyProcessLimit; //获取允许的后台进程数16
//为后台进程、空进程开辟位置,此处计算结果为(906-900+1)/2 = 3
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ //
- ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs; // 计算当前系统中空进程的数量
int emptyFactor = numEmptyProcs/numSlots;// 计算每个slot中保存的进程数量
int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ; // 后台进程的adj= 900
int nextCachedAdj = curCachedAdj+1; // 下一个位置+1
int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ; // 空进程adj=900
int nextEmptyAdj = curEmptyAdj+2; // 下一个位置+2
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i); // 遍历所有的进程ProcessRecord ,计算oom_adj的值
if (!app.killedByAm && app.thread != null) {
computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
case ActivityManager.PROCESS_STATE_CACHED_RECENT:
app.curRawAdj = curCachedAdj; //赋值后台进程
app.curAdj = app.modifyRawOomAdj(curCachedAdj);
if (curCachedAdj != nextCachedAdj) {
stepCached++; // 累计当前adj值中保存的进程数
if (stepCached >= cachedFactor) { // 超过每个slot数量后使用下一个next slot位置
stepCached = 0;
curCachedAdj = nextCachedAdj;
nextCachedAdj += 2;
if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
}
}
}
break;
default:
app.curRawAdj = curEmptyAdj; // 赋值空进程
app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
break;
}
}
}
}
}
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (!app.killedByAm && app.thread != null) {
applyOomAdjLocked(app, true, now, nowElapsed); // 更新进程的adj值
switch (app.curProcState) {
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
mNumCachedHiddenProcs++;
numCached++; // 计算后台进程
if (numCached > cachedProcessLimit) { // 如果后台进程超过上限则杀掉进程
app.kill("cached #" + numCached, true);
}
break;
case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
//系统内部会定义一个允许保留空进程的数量且不需要执行回收的,当超过此数量则执行杀死
if (numEmpty > mConstants.CUR_TRIM_EMPTY_PROCESSES
&& app.lastActivityTime < oldTime) {//并且当前进程空闲时间超过设置要求的时间30min
app.kill("empty for "
+ ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
/ 1000) + "s", true);
} else {
numEmpty++;
if (numEmpty > emptyProcessLimit) {// 空进程超过限制杀掉进程,此处设置为16
app.kill("empty #" + numEmpty, true);
}
}
break;
default:
mNumNonCachedProcs++;
break;
}
//对于单独进程的空进程,直接杀死进程
if (app.isolated && app.services.size() <= 0 && app.isolatedEntryPoint == null) {
app.kill("isolated not needed", true);
} else {
final UidRecord uidRec = app.uidRecord;
if (uidRec != null) {
uidRec.ephemeral = app.info.isInstantApp();
if (uidRec.curProcState > app.curProcState) { // 更新用户的最高优先级
uidRec.curProcState = app.curProcState;
}
}
}
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) {
numTrimming++; // 统计优先级低于Home进程的,表明此更加进程不重要
}
}
}
在updateOomAdjLocked()中主要是计算进程的优先级,同时决定进程的生死,主要任务如下:
final int numCachedAndEmpty = numCached + numEmpty; // 计算后台进程和空进程数量之和,确定内存等级
int memFactor;
//如果后台进程小于5,空进程小于8
if (numCached <= mConstants.CUR_TRIM_CACHED_PROCESSES
&& numEmpty <= mConstants.CUR_TRIM_EMPTY_PROCESSES) {
if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {//总计小于等于 3
memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL; // 设置为CRITICAL级别
} else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) { //总计不超过5
memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW; // 设置为Low级别
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE; // 设置为MODERATE级别
}
} else {
memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL; // 设置为normal级别
}
mLastMemoryLevel = memFactor; // 保存最新等级
if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) { //当内存不为normal时,需要执行内存回收
if (mLowRamStartTime == 0) {
mLowRamStartTime = now; // 保存低内存时间
}
}
switch (memFactor) { //根据内存状况,设置fgTrimLevel等级
case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
break;
case ProcessStats.ADJ_MEM_FACTOR_LOW:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
break;
default:
fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
break;
}
for (int i=N-1; i>=0; i--) {
ProcessRecord app = mLruProcesses.get(i);
if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
&& !app.killedByAm) { // 处理优先级低于Home进程的,调用scheduleTrimMemory()方法执行内存回收
app.thread.scheduleTrimMemory(curLevel);
}else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT
&& !app.killedByAm) { // 处理优先级为HEAVY_WEIGHT
if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
&& app.thread != null) {
app.thread.scheduleTrimMemory(
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
}
}else { // 处理后台进程
if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
|| app.systemNoUi) && app.pendingUiClean) {
final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
if (app.trimMemoryLevel < level && app.thread != null) {
try {
app.thread.scheduleTrimMemory(level);
} catch (RemoteException e) {
}
}
app.pendingUiClean = false;
}
if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
try {
app.thread.scheduleTrimMemory(fgTrimLevel);
} catch (RemoteException e) {
}
}
app.trimMemoryLevel = fgTrimLevel;
}
}
本部分主要是处理系统内存紧张时,通知运行的进程回收内存的机制:
到此Android系统中对进程的管理就分析结束了,简单的说就是会不断计算和更新进程的优先级,然后根据设置的上限条件决定杀死哪些进程保留哪些进程,对于存活的进程Amdroid中也会进行进一步操作,就是通知进程的内存回收,程序根据系统中进程的存活量确定当前内存等级,然后根据进程优先级调用系统的内存回收方法,处理上面的整个流程外,还有一个方法没有分析就是computeOomAdjLocked(),下面看看它是如何计算进程优先级的;
11517 if (app == TOP_APP) {//1、 判断当前进程是否为TOP_APP,TOP_APP保存当前正在运行的ProcessRecord对象
11519 adj = FOREGROUND_APP_ADJ; // 设置为FOREGROUND_APP_ADJ,优先级最高为0
11520 schedGroup = Process.THREAD_GROUP_DEFAULT;
11521 app.adjType = "top-activity";
11522 } else if (app.instrumentationClass != null) { // 2、是否有自定义的instrumentationClass
11524 adj = FOREGROUND_APP_ADJ; // 设置为优先级最高0
11525 schedGroup = Process.THREAD_GROUP_DEFAULT;
11526 app.adjType = "instrumentation";
11527 } else if (app.curReceiver != null || // 3、判断有持久的Activity、Service、Receiver设置为优先级最高 0
11528 (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
11531 adj = FOREGROUND_APP_ADJ;
11532 schedGroup = Process.THREAD_GROUP_DEFAULT;
11533 app.adjType = "broadcast";
11534 } else if (app.executingServices.size() > 0) {
11537 adj = FOREGROUND_APP_ADJ;
11538 schedGroup = Process.THREAD_GROUP_DEFAULT;
11539 app.adjType = "exec-service";
11540 } else if (app.foregroundServices) { // 4、判断当前是否为前台服务,设置优先级为 1
11542 adj = PERCEPTIBLE_APP_ADJ;
11543 schedGroup = Process.THREAD_GROUP_DEFAULT;
11544 app.adjType = "foreground-service";
11545 } else if (app.forcingToForeground != null) { //5、判断用户是否强制调到前台,设置优先级1
11547 adj = PERCEPTIBLE_APP_ADJ;
11548 schedGroup = Process.THREAD_GROUP_DEFAULT;
11549 app.adjType = "force-foreground";
11550 app.adjSource = app.forcingToForeground;
11551 } else if (app == mHomeProcess) { //6、判断是否为Home进程,设置优先级 4
11559 adj = HOME_APP_ADJ;
11560 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
11561 app.adjType = "home";
}else if ((N=app.activities.size()) != 0) {
11568 N = app.activities.size();
11569 for (int j=0; j<N; j++) {
11570 if (app.activities.get(j).visible) {
11572 app.hidden = false;
11573 adj = VISIBLE_APP_ADJ;
11574 schedGroup = Process.THREAD_GROUP_DEFAULT; //7、包含Activity数目大于0,且包含可见的Activity存在,设置1
11575 app.adjType = "visible";
11576 break;
11577 }
11578 }
11579 }else {
11582 app.hidden = true;
11583 app.empty = true;
11584 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
11585 adj = hiddenAdj; // 8、其他进程设置为hiddenAdj
11586 app.adjType = "bg-empty";
11587 }
app.adjSeq = mAdjSeq;
app.curRawAdj = adj; // 赋值第一次估算的adj
if (mBackupTarget != null && app == mBackupTarget.app) {//9、判断是否为mBackuptarget进程,设置优先级 2
11600 if (adj > BACKUP_APP_ADJ) {
11602 adj = BACKUP_APP_ADJ;
11603 app.adjType = "backup";
11604 app.hidden = false;
11605 }
11606 }
// 10、判断app中服务进程(进程中运行Service但不属于前台服务)
11608 if (app.services.size() != 0 && (adj > FOREGROUND_APP_ADJ
11609 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
Iterator<ServiceRecord> jt = app.services.iterator();
11614 while (jt.hasNext() && adj > FOREGROUND_APP_ADJ) {
11615 ServiceRecord s = jt.next(); //遍历所有的Service
11616 if (s.startRequested) { // 根据startRequested判断Service是否启动,如果启动过超过待机时间,设置优先级 2
adj = SECONDARY_SERVER_ADJ;
}
}
if (cr.binding.client == app) { // 如果Service有绑定的app,则保护app的优先级即可
11649 continue; }
int clientAdj = computeOomAdjLocked(client, myHiddenAdj, TOP_APP, true); // 递归调用第二次估算,以优先级高为准
ActivityRecord a = cr.activity; // 判断是否进程是否包含resume或pause的Activity,设置为优先级 0
11688 if (a != null && adj > FOREGROUND_APP_ADJ && (a.state == ActivityState.RESUMED
11690 || a.state == ActivityState.PAUSING)) {
11691 adj = FOREGROUND_APP_ADJ;
11692 schedGroup = Process.THREAD_GROUP_DEFAULT;
}
app.curAdj = adj; // 最终的adj
app.curSchedGroup = schedGroup;
关于应用进程优先级的更新细节见代码注释,源码部分很多请读者自行查看,主要就是根据前台进程、前台服务、后台进程等设置对应的adj的值,在计算完adj之后每个进程都有了各自的优先级顺序,将最终计算的结果保存在app.curAdj中,那此时就代表当前进程的优先级了;
本文从源码的角度分析了AMS是如何管理内存的,主要分析了AMS如何管理应用程序进程管理、OOM Killer机制如何设备中的进程管理,通过对整个内存管理的学习,对系统程序之间的协调运作有了更好的认知,那关于AMS的部分就到此结束了。