一纽什、 進(jìn)程生命周期
Android系統(tǒng)將盡量長(zhǎng)時(shí)間地保持應(yīng)用進(jìn)程纪岁,但為了新建進(jìn)程或運(yùn)行更重要的進(jìn)程卒密,最終需要清除舊進(jìn)程來(lái)回收內(nèi)存。 為了確定保留或終止哪些進(jìn)程岳掐,系統(tǒng)會(huì)根據(jù)進(jìn)程中正在運(yùn)行的組件以及這些組件的狀態(tài)凭疮,將每個(gè)進(jìn)程放入“重要性層次結(jié)構(gòu)”中。 必要時(shí)串述,系統(tǒng)會(huì)首先消除重要性最低的進(jìn)程执解,然后是清除重要性稍低一級(jí)的進(jìn)程,依此類推纲酗,以回收系統(tǒng)資源衰腌。
進(jìn)程的重要性,劃分5級(jí):
前臺(tái)進(jìn)程(Foreground process)
可見(jiàn)進(jìn)程(Visible process)
服務(wù)進(jìn)程(Service process)
后臺(tái)進(jìn)程(Background process)
空進(jìn)程(Empty process)
前臺(tái)進(jìn)程的重要性最高觅赊,依次遞減右蕊,空進(jìn)程的重要性最低,下面分別來(lái)闡述每種級(jí)別的進(jìn)程
1.1 Foreground process
用戶當(dāng)前操作所必需的進(jìn)程吮螺。通常在任意給定時(shí)間前臺(tái)進(jìn)程都為數(shù)不多饶囚。只有在內(nèi)存不足以支持它們同時(shí)繼續(xù)運(yùn)行這一萬(wàn)不得已的情況下,系統(tǒng)才會(huì)終止它們鸠补。
- 擁有用戶正在交互的 Activity(已調(diào)用onResume())
- 擁有某個(gè) Service萝风,后者綁定到用戶正在交互的 Activity
- 擁有正在“前臺(tái)”運(yùn)行的 Service(服務(wù)已調(diào)用 startForeground())
- 擁有正執(zhí)行一個(gè)生命周期回調(diào)的 Service(onCreate()、onStart() 或 onDestroy())
- 擁有正執(zhí)行其 onReceive() 方法的 BroadcastReceiver
1.2 Visible process
沒(méi)有任何前臺(tái)組件莫鸭、但仍會(huì)影響用戶在屏幕上所見(jiàn)內(nèi)容的進(jìn)程闹丐。可見(jiàn)進(jìn)程被視為是極其重要的進(jìn)程被因,除非為了維持所有前臺(tái)進(jìn)程同時(shí)運(yùn)行而必須終止卿拴,否則系統(tǒng)不會(huì)終止這些進(jìn)程。
- 擁有不在前臺(tái)梨与、但仍對(duì)用戶可見(jiàn)的 Activity(已調(diào)用onPause())堕花。
- 擁有綁定到可見(jiàn)(或前臺(tái))Activity 的 Service
1.3 Service process
盡管服務(wù)進(jìn)程與用戶所見(jiàn)內(nèi)容沒(méi)有直接關(guān)聯(lián),但是它們通常在執(zhí)行一些用戶關(guān)心的操作(例如粥鞋,在后臺(tái)播放音樂(lè)或從網(wǎng)絡(luò)下載數(shù)據(jù))缘挽。因此,除非內(nèi)存不足以維持所有前臺(tái)進(jìn)程和可見(jiàn)進(jìn)程同時(shí)運(yùn)行,否則系統(tǒng)會(huì)讓服務(wù)進(jìn)程保持運(yùn)行狀態(tài)壕曼。
- 正在運(yùn)行startService()方法啟動(dòng)的服務(wù)苏研,且不屬于上述兩個(gè)更高類別進(jìn)程的進(jìn)程。
1.4 Background process
后臺(tái)進(jìn)程對(duì)用戶體驗(yàn)沒(méi)有直接影響腮郊,系統(tǒng)可能隨時(shí)終止它們摹蘑,以回收內(nèi)存供前臺(tái)進(jìn)程、可見(jiàn)進(jìn)程或服務(wù)進(jìn)程使用轧飞。 通常會(huì)有很多后臺(tái)進(jìn)程在運(yùn)行衅鹿,因此它們會(huì)保存在LRU列表中,以確保包含用戶最近查看的Activity的進(jìn)程最后一個(gè)被終止过咬。如果某個(gè) Activity 正確實(shí)現(xiàn)了生命周期方法大渤,并保存了其當(dāng)前狀態(tài),則終止其進(jìn)程不會(huì)對(duì)用戶體驗(yàn)產(chǎn)生明顯影響掸绞,因?yàn)楫?dāng)用戶導(dǎo)航回該 Activity 時(shí)泵三,Activity 會(huì)恢復(fù)其所有可見(jiàn)狀態(tài)。
- 對(duì)用戶不可見(jiàn)的Activity的進(jìn)程(已調(diào)用Activity的onStop()方法)
1.5 Empty process
保留這種進(jìn)程的的唯一目的是用作緩存衔掸,以縮短下次在其中運(yùn)行組件所需的啟動(dòng)時(shí)間切黔。 為使總體系統(tǒng)資源在進(jìn)程緩存和底層內(nèi)核緩存之間保持平衡,系統(tǒng)往往會(huì)終止這些進(jìn)程具篇。
- 不含任何活動(dòng)應(yīng)用組件的進(jìn)程
二、Lowmemorykiller
2.1 ADJ級(jí)別
定義在ProcessList.java文件凌埂,oom_adj劃分為16級(jí)驱显,從-1000到1001之間取值。
ADJ級(jí)別 | 取值 | 解釋 |
---|---|---|
UNKNOWN_ADJ | 1001 | 一般指將要會(huì)緩存進(jìn)程瞳抓,無(wú)法獲取確定值 |
CACHED_APP_MAX_ADJ | 999 | 不可見(jiàn)進(jìn)程的adj最大值 |
CACHED_APP_MIN_ADJ | 900 | 不可見(jiàn)進(jìn)程的adj最小值 |
SERVICE_B_AD | 800 | B List中的Service(較老的埃疫、使用可能性更小) |
PREVIOUS_APP_ADJ | 700 | 上一個(gè)App的進(jìn)程(往往通過(guò)按返回鍵) |
HOME_APP_ADJ | 600 | Home進(jìn)程 |
SERVICE_ADJ | 500 | 服務(wù)進(jìn)程(Service process) |
HEAVY_WEIGHT_APP_ADJ | 400 | 后臺(tái)的重量級(jí)進(jìn)程孩哑,system/rootdir/init.rc文件中設(shè)置 |
BACKUP_APP_ADJ | 300 | 備份進(jìn)程 |
PERCEPTIBLE_APP_ADJ | 200 | 可感知進(jìn)程栓霜,比如后臺(tái)音樂(lè)播放 |
VISIBLE_APP_ADJ | 100 | 可見(jiàn)進(jìn)程(Visible process) |
FOREGROUND_APP_ADJ | 50 | 前臺(tái)進(jìn)程(Foreground process) |
PERSISTENT_SERVICE_ADJ | -700 | 關(guān)聯(lián)著系統(tǒng)或persistent進(jìn)程 |
PERSISTENT_PROC_ADJ | -800 | 系統(tǒng)persistent進(jìn)程,比如telephony |
SYSTEM_ADJ | -900 | 系統(tǒng)進(jìn)程 |
NATIVE_ADJ | -1000 | native進(jìn)程(不被系統(tǒng)管理) |
這里按照Android對(duì)進(jìn)程的分類横蜒,粗略劃分一下不同oom_adj對(duì)應(yīng)的場(chǎng)景
2.2 進(jìn)程state級(jí)別
定義在ActivityManager.java文件胳蛮,process_state,從-1到20之間取值丛晌。
state級(jí)別 | 取值 | 解釋 |
---|---|---|
PROCESS_STATE_NONEXISTENT | 20 | 進(jìn)程不存在 |
PROCESS_STATE_CACHED_EMPTY | 19 | 進(jìn)程處于cached狀態(tài)仅炊,且為空進(jìn)程 |
PROCESS_STATE_CACHED_RECENT | 18 | 與recent中關(guān)聯(lián)的緩存進(jìn)程 |
PROCESS_STATE_CACHED_ACTIVITY_CLIENT | 17 | 托管存在客戶端的Activity的進(jìn)程 |
PROCESS_STATE_CACHED_ACTIVITY | 16 | 后臺(tái)托管有Activity的進(jìn)程 |
PROCESS_STATE_LAST_ACTIVITY | 15 | 后臺(tái)進(jìn)程,但是托管了用戶最后運(yùn)行的Activity |
PROCESS_STATE_HOME | 14 | Home進(jìn)程 |
PROCESS_STATE_HEAVY_WEIGHT | 13 | 重量級(jí)進(jìn)程 |
PROCESS_STATE_TOP_SLEEPING | 12 | 和PROCESS_STATE_TOP一樣澎蛛,但是區(qū)別是手機(jī)處于sleeping狀態(tài) |
PROCESS_STATE_RECEIVER | 11 | 后臺(tái)進(jìn)程抚垄,且正在運(yùn)行receiver |
PROCESS_STATE_SERVICE | 10 | 后臺(tái)進(jìn)程,且正在運(yùn)行service |
PROCESS_STATE_BACKUP | 9 | 備份進(jìn)程 |
PROCESS_STATE_TRANSTENT_BACKGROUND | 8 | 對(duì)于用戶比較重要的后臺(tái)進(jìn)程 |
PROCESS_STATE_IMPORTANT_BACKGROUND | 7 | 對(duì)用戶很重要的進(jìn)程,用戶可感知其存在 |
PROCESS_STATE_IMPORTANT_FOREGROUND | 6 | 對(duì)于用戶比較重要的前臺(tái)進(jìn)程 |
PROCESS_STATE_BOUND_FOREGROUND_SERVICE | 5 | 通過(guò)bind的形式托管前臺(tái)服務(wù)的進(jìn)程 |
PROCESS_STATE_FOREGROUND_SERVICE | 4 | 托管前臺(tái)服務(wù)的進(jìn)程 |
PROCESS_STATE_BOUND_TOP | 3 | 進(jìn)程綁定到一個(gè)TOP應(yīng)用呆馁。它的排名低于SERVICE_LOCATION |
PROCESS_STATE_TOP | 2 | 涵蓋了用戶可見(jiàn)活動(dòng)的進(jìn)程 |
PROCESS_STATE_PERSISTENT_UI | 1 | 系統(tǒng)persistent進(jìn)程桐经,正在進(jìn)行UI相關(guān)的操作 |
PROCESS_STATE_PERSISTENT | 0 | 系統(tǒng)persistent進(jìn)程 |
PROCESS_STATE_UNKNOWN | -1 | 不存在的進(jìn)程 |
2.3 lmk策略
Lowmemorykiller根據(jù)當(dāng)前可用內(nèi)存情況來(lái)進(jìn)行進(jìn)程釋放,總設(shè)計(jì)了6個(gè)級(jí)別浙滤,即Lowmemorykiller的殺進(jìn)程的6檔阴挣,如下:
- CACHED_APP_MAX_ADJ
- CACHED_APP_MIN_ADJ
- BACKUP_APP_ADJ
- PERCEPTIBLE_APP_ADJ
- VISIBLE_APP_ADJ
- FOREGROUND_APP_ADJ
系統(tǒng)內(nèi)存從很寬裕到不足,Lowmemorykiller也會(huì)相應(yīng)地從CACHED_APP_MAX_ADJ(第1檔)開(kāi)始?xì)⑦M(jìn)程瓷叫,如果內(nèi)存還不足屯吊,那么會(huì)殺CACHED_APP_MIN_ADJ(第2檔),不斷深入摹菠,直到滿足內(nèi)存閾值條件盒卸。
三、 進(jìn)程調(diào)度adj算法
ADJ算法的核心方法:
-
updateOomAdjLocked
:更新adj次氨,當(dāng)目標(biāo)進(jìn)程為空蔽介,或者被殺則返回false;否則返回true; -
computeOomAdjLocked
:計(jì)算adj煮寡,返回計(jì)算后RawAdj值; -
applyOomAdjLocked
:應(yīng)用adj虹蓄,當(dāng)需要?dú)⒌裟繕?biāo)進(jìn)程則返回false;否則返回true幸撕。
調(diào)整adj的3的方法薇组,最為常見(jiàn)的方法便是updateOomAdjLocked,這也是其他各個(gè)方法在需要更新adj時(shí)會(huì)調(diào)用的方法坐儿。
四律胀、ADJ的更新時(shí)機(jī)
哪些場(chǎng)景下都會(huì)觸發(fā)updateOomAdjLocked來(lái)更新進(jìn)程adj:
4.1 Activity
- ASS.realStartActivityLocked: 啟動(dòng)Activity
- AS.resumeTopActivityInnerLocked: 恢復(fù)棧頂Activity
- AS.finishCurrentActivityLocked: 結(jié)束當(dāng)前Activity
- AS.destroyActivityLocked: 摧毀當(dāng)前Activity
4.2 Service
位于ActiveServices.java
- realStartServiceLocked: 啟動(dòng)服務(wù)
- bindServiceLocked: 綁定服務(wù)(只更新當(dāng)前app)
- unbindServiceLocked: 解綁服務(wù) (只更新當(dāng)前app)
- bringDownServiceLocked: 結(jié)束服務(wù) (只更新當(dāng)前app)
- sendServiceArgsLocked: 在bringup或則cleanup服務(wù)過(guò)程調(diào)用 (只更新當(dāng)前app)
4.3 broadcast
- BQ.processNextBroadcast: 處理下一個(gè)廣播
- BQ.processCurBroadcastLocked: 處理當(dāng)前廣播
- BQ.deliverToRegisteredReceiverLocked: 分發(fā)已注冊(cè)的廣播 (只更新當(dāng)前app)
4.4 ContentProvider
- AMS.removeContentProvider: 移除provider
- AMS.publishContentProviders: 發(fā)布provider (只更新當(dāng)前app)
- AMS.getContentProviderImpl: 獲取provider (只更新當(dāng)前app)
4.5 Process
位于ActivityManagerService.java
- setSystemProcess: 創(chuàng)建并設(shè)置系統(tǒng)進(jìn)程
- addAppLocked: 創(chuàng)建persistent進(jìn)程
- attachApplicationLocked: 進(jìn)程創(chuàng)建后attach到system_server的過(guò)程;
- trimApplications: 清除沒(méi)有使用app
- appDiedLocked: 進(jìn)程死亡
- killAllBackgroundProcesses: 殺死所有后臺(tái)進(jìn)程.即(ADJ>9或removed=true的普通進(jìn)程)
- killPackageProcessesLocked: 以包名的形式 殺掉相關(guān)進(jìn)程;
五、updateOomAdjLocked
5.1 重要方法
/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@GuardedBy("this")
final void updateOomAdjLocked(String oomAdjReason) {
mOomAdjuster.updateOomAdjLocked(oomAdjReason);
}
/*
* Update OomAdj for a specific process and its reachable processes.
* @param app The process to update
* @param oomAdjReason
*/
@GuardedBy("this")
final void updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
}
/frameworks/base/services/core/java/com/android/server/am/OomAdjuster.java
/**
* Update OomAdj for all processes in LRU list
*/
@GuardedBy("mService")
void updateOomAdjLocked(String oomAdjReason) {
//獲取棧頂Activity
final ProcessRecord topApp = mService.getTopAppLocked();
updateOomAdjLockedInner(oomAdjReason, topApp , null, null, true, true);
}
/**
* Update OomAdj for all processes within the given list (could be partial), or the whole LRU
* list if the given list is null; when it's partial update, each process's client proc won't
* get evaluated recursively here.
*/
@GuardedBy("mService")
private void updateOomAdjLockedInner(String oomAdjReason, final ProcessRecord topApp,
ArrayList<ProcessRecord> processes, ActiveUids uids, boolean potentialCycles,
boolean startProfiling) {
private final boolean computeOomAdjLocked(ProcessRecord app, int cachedAdj,
ProcessRecord topApp, boolean doingAll, long now, boolean cycleReEval,
boolean computeClients) {
/** Applies the computed oomadj, procstate and sched group values and freezes them in set* */
@GuardedBy("mService")
private final boolean applyOomAdjLocked(ProcessRecord app, boolean doingAll, long now,
long nowElapsed) {
等重要方法貌矿。
- updateOomAdjLocked在應(yīng)用進(jìn)程的組件運(yùn)行狀態(tài)發(fā)生改變時(shí)被調(diào)用炭菌,比如有Service啟動(dòng),有廣播接收者收到廣播逛漫,有Activity啟動(dòng)等黑低,這很好理解,因?yàn)檫M(jìn)程重要性的計(jì)算就依賴于組件運(yùn)行狀態(tài)酌毡,既然組件運(yùn)行狀態(tài)發(fā)生了改變克握,就應(yīng)該實(shí)時(shí)更新;
- computeOomAdjLocked根據(jù)一定規(guī)則計(jì)算出三個(gè)狀態(tài)值枷踏,這個(gè)規(guī)則跟Android將進(jìn)程劃分的5個(gè)優(yōu)先級(jí)有關(guān)系玛荞,即前臺(tái)進(jìn)程、可見(jiàn)進(jìn)程呕寝、服務(wù)進(jìn)程勋眯、后臺(tái)進(jìn)程婴梧、空進(jìn)程,這里不詳細(xì)說(shuō)明客蹋;
- applyOomAdjLocked將computeOomAdjLocked計(jì)算出的三個(gè)狀態(tài)值應(yīng)用起來(lái)塞蹭,即真正發(fā)揮這三個(gè)狀態(tài)值的作用。