提起android的进程回收机制,大家所熟知的是Android的lowmemroykiller的机制。当系统可用内存低于某个阀值时,即会杀死这个阀值对应的Adj值的所有应用。但是本篇文章并为是要介绍Lowmemorykiller的机制,而是要搞清楚在未触发Android低杀机制时,Android是否有某种策略对进程进行回收。因为随着硬件成本低降低,各品牌手机低配置也是越来越高,4G及6G内存的手机层出不穷,在这类高内存配置的手机下,按照lowmemorykiller的默认参数来看,低杀出现的概率也小了很多。通过对AMS中的updateOomAdjLocked()方法的分析即可了解Android在lowmemorykiller之外的Android进程回收机制。
那我们按顺序来介绍updateOomAdjLocked方法。首先时初始化一些变量用以后续的操作。TOP_ACT和TOP_APP表示当前处于前台的app(若无app 处于前台则是TASK栈栈顶的应用);根据LRU列表得到当前系统的存在的进程数量N;重置用户组中的进程状态的动作。TOP_ACT,rankTaskLayersIfNeeded方法,mAdjSeq这些变量主要是用于后面方法中会待调用的computateOomAdjLocked()方法,这不是我们本篇的重点,所以不再展开进行详解。
final ActivityRecord TOP_ACT = resumedAppLocked();
final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
final long now = SystemClock.uptimeMillis();
final long nowElapsed = SystemClock.elapsedRealtime();
final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
final int N = mLruProcesses.size();
...
// Reset state in all uid records.
for (int i=mActiveUids.size()-1; i>=0; i--) {
final UidRecord uidRec = mActiveUids.valueAt(i);
if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Starting update of " + uidRec);
uidRec.reset();
}
mStackSupervisor.rankTaskLayersIfNeeded();
mAdjSeq++;
mNewNumServiceProcs = 0;
mNewNumAServiceProcs = 0;
mProcessLimit表示的是系统允许保留的后台进程和empty进程的总和,初始化为ProcessList.MAX_CACHED_APPS常量,默认为32。Android自身的机制在运行中不会主动修改这个值,但用户可以在“开发者选项”的“后台进程限制”这一项来修改该值。emptyProcessLimit和cachedProcessLimit分别为根据mProcessLimit的值计算出的允许的后台进程和empty进程的最大数量。当mProcessLimit不小于0且不等于1时,后台进程和empty进程和后台进程的数量各占mProcessLimit的一半。 本文讲的后台进程是指cached进程里的非empty的进程,而不包含后台服务进程。
final int emptyProcessLimit;
final int cachedProcessLimit;
if (mProcessLimit <= 0) {
emptyProcessLimit = cachedProcessLimit = 0;
} else if (mProcessLimit == 1) {
emptyProcessLimit = 1;
cachedProcessLimit = 0;
} else {
emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
cachedProcessLimit = mProcessLimit - emptyProcessLimit;
}
再往下是初始化一些变量的操作,这里要重点注意numSlots所表达的意思。ProcessList.CACHED_APP_MAX_ADJ和Process.CACHED_APP_MIN_ADJ常量系统默认的值分别为906和900,表示的是后台进程和empty进程分配的值是在900至906之间,共有7个值。numSloas计算过程中除以2是因为每个槽配置到进程包含后台进程和empty进程两种,两种进程需用不同adj值表示,所以每个槽包含两个adj值的分配空间,所以需要除以二,计算出来的numSlots值为3。emptyFactor表示每个槽中需要放置几个empty进程,是根据当前empty进程总数决定的,cachedFactor即是表示需要放置几个后台进程到每个槽中。
为便于理解,结合后面代码逻辑举例来讲,比如后台此时有15个cahcedProcess(后台进程)和12个emptyProcess,则会将15/3=5个cachedProcess设置到在第一个槽(可分配900,901这两个oom_adj值)中,oom_adj设置为900;将12/4=4个emptyProcess设置在第一槽,oom_adj值设置为901;然后再设置5个cachedProcess和4个emptyProcess的oom_adj值分别为902和903,即第二个槽。
// Let's determine how many processes we have running vs.
// how many slots we have for background processes; we may want
// to put multiple processes in a slot of there are enough of
// them.
int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
- ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
if (numEmptyProcs > cachedProcessLimit) {
// If there are more empty processes than our limit on cached
// processes, then use the cached process limit for the factor.
// This ensures that the really old empty processes get pushed
// down to the bottom, so if we are running low on memory we will
// have a better chance at keeping around more cached processes
// instead of a gazillion empty processes.
numEmptyProcs = cachedProcessLimit;
}
int emptyFactor = numEmptyProcs/numSlots;
if (emptyFactor < 1) emptyFactor = 1;
int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
if (cachedFactor < 1) cachedFa