- 相關(guān)推薦
Android操作系統(tǒng)的內(nèi)存回收的策略是什么
Android 是一款基于 Linux 內(nèi)核,面向移動(dòng)終端的操作系統(tǒng)。為適應(yīng)其作為移動(dòng)平臺(tái)操作系統(tǒng)的特殊需要,谷歌對(duì)其做了特別的設(shè)計(jì)與優(yōu)化,使應(yīng)用程序關(guān)閉但不退出,并由操作系統(tǒng)進(jìn)行進(jìn)程的回收管理。本文在 Application Framework 與 Linux 內(nèi)核兩個(gè)層次上,以進(jìn)程為粒度,對(duì) Android 操作系統(tǒng)的進(jìn)程資源回收機(jī)制進(jìn)行了剖析。讀者可以從本文獲得對(duì) Android 應(yīng)用程序的生存周期的進(jìn)一步理解,從而更加合理、高效地構(gòu)建應(yīng)用程序。
Android 操作系統(tǒng)中的內(nèi)存回收可分為兩個(gè)層次:
1、默認(rèn)內(nèi)存回收、即Application Framework 層的默認(rèn)回收。
2、內(nèi)核級(jí)內(nèi)存回收。
Linux 內(nèi)核中的內(nèi)存回收 lowmemorykiller、OOM_killer。
默認(rèn)內(nèi)存回收:(代碼可查閱 ActivityManagerService.java類)回收動(dòng)作入口activityIdleInternal()。
Android 系統(tǒng)中內(nèi)存回收的觸發(fā)點(diǎn)大致可分為三種情況。
第一,用戶程序調(diào)用 StartActivity(), 使當(dāng)前活動(dòng)的 Activity 被覆蓋;
第二,用戶按 back 鍵,退出當(dāng)前應(yīng)用程序;第三,啟動(dòng)一個(gè)新的應(yīng)用程序。
這些能夠觸發(fā)內(nèi)存回收的事件最終調(diào)用的函數(shù)接口就是 activityIdleInternal()。當(dāng) ActivityManagerService 接收到異步消息 IDLE_TIMEOUT_MSG 或者 IDLE_NOW_MSG 時(shí),activityIdleInternal() 將會(huì)被調(diào)用。 IDLE_NOW_MSG 由 Activity 的切換以及 Activiy 焦點(diǎn)的改變等事件引發(fā),IDLE_TIMEOUT_MSG 在 Activity 啟動(dòng)超時(shí)的情況下引發(fā),一般這個(gè)超時(shí)時(shí)間設(shè)為 10s,如果 10s 之內(nèi)一個(gè) Activity 依然沒(méi)有成功啟動(dòng),那么將發(fā)送異步消息 IDLE_TIMEOUT_MSG 進(jìn)行資源回收。activityIdleInternal() 的主要任務(wù)是改變系統(tǒng)中 Activity 的狀態(tài)信息,并將其添加到不同狀態(tài)列表中。它的主要工如下:
首先,調(diào)用 scheduleAppGcsLocked() 方法通知所有進(jìn)行中的任務(wù)進(jìn)行垃圾回收。scheduleAppGcsLocked() 將進(jìn)行調(diào)度 JVM 的 garbage collect,回收一部分內(nèi)存空間,這里僅僅是通知每個(gè)進(jìn)程自行進(jìn)程垃圾檢查并調(diào)度回收時(shí)間,而非同步回收。
然后,取出 mStoppingActivities 和 mFinishigActivities 列表中的所有內(nèi)容,暫存在臨時(shí)變量中。這兩個(gè)列表分別存儲(chǔ)了當(dāng)前狀態(tài)為 stop 和 finishi 的 activity 對(duì)象。對(duì)于 stop 列表,如果其中的 activity 的 finish 狀態(tài)為 true,判斷是不是要立即停止,如果要立即停止則調(diào)用 destroyActivityLocked() 通知目標(biāo)進(jìn)程調(diào)用 onDestroy() 方法,否則,先調(diào)用resumeTopActivity() 運(yùn)行下一個(gè) Activity。如果 finish 狀態(tài)為 false,則調(diào)用 stopActivityLocked() 通知客戶進(jìn)程停止該 Activity,這種情況一般發(fā)生在調(diào)用 startActivity() 后。對(duì)于 finish 列表,直接調(diào)用 destroyActivityLocked() 通知客戶進(jìn)程銷毀目標(biāo) Activity。這里的 destroyActivityLocked 等函數(shù)并沒(méi)有真正意義上改變內(nèi)存的使用,只是將其狀態(tài)改變?yōu)椤霸试S回收”,真正的回收在下面即將調(diào)用的 trimApplications() 函數(shù)中。
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)當(dāng)程序執(zhí)行到 trimApplications() 之后,首先檢查 mRemovedProcesses 列表中的進(jìn)程。mRemovedProcesses 列表中主要包含了 crash 的進(jìn)程、5 秒內(nèi)沒(méi)有響應(yīng)并被用戶選在強(qiáng)制關(guān)閉的進(jìn)程、以及應(yīng)用開(kāi)發(fā)這調(diào)用 killBackgroundProcess 想要?dú)⑺赖倪M(jìn)程。調(diào)用 Process.killProcess 將所有此類進(jìn)程全部殺死。
(2)調(diào)用 updateOomAdjLocked() 函數(shù),若成功返回,說(shuō)明 Linux 內(nèi)核支持 setOomAdj() 接口,updateOomAdjLocked 將修改 adj 的值并通知 linux 內(nèi)核,內(nèi)核根據(jù) adj 值以及內(nèi)存使用情況動(dòng)態(tài)管理進(jìn)程資源(lowmemorykiller 和 oom_killer)。若 updateOomAdjLocked() 返回為假,則表示當(dāng)前系統(tǒng)不支持 setOomAdj() 接口,將在本地進(jìn)行默認(rèn)的資源回收。
。3)最后,如果當(dāng)前依然運(yùn)行了過(guò)多的 Activity,對(duì)多余的 Activity 進(jìn)行回收。 trimApplications() 的大多數(shù)的代碼都在處理 Oom_killer 不存在情況下的默認(rèn)資源回收,下面對(duì)其默認(rèn)回收過(guò)程(即代碼中標(biāo)記(2)的位置)進(jìn)行進(jìn)一步分析。其回收過(guò)程可大致描述如下。
步驟一,獲取當(dāng)前所有運(yùn)行的進(jìn)程 mLruProcesses,mLruProcesses 中的排序規(guī)則是按最近使用時(shí)間。對(duì) mLruProcesses 中不能被關(guān)閉的進(jìn)程進(jìn)行計(jì)數(shù),這些不能被關(guān)閉的進(jìn)程包括運(yùn)行 service 的進(jìn)程,運(yùn)行broadcast receiver 的進(jìn)程等。
步驟二, 設(shè)當(dāng)前最大運(yùn)行進(jìn)程數(shù) curMaxProcs = curMaxProcs + numServiceProcs(即默認(rèn)最大進(jìn)程數(shù)與運(yùn)行 Service 的進(jìn)程數(shù)之和),如果當(dāng)前進(jìn)程的數(shù)量 mRemovedProcesses.size() 大于這個(gè)值,則遍歷所有當(dāng)前運(yùn)行的進(jìn)程,殺死符合條件的那些進(jìn)程并釋放內(nèi)存。進(jìn)程被殺死的條件是:必須是非 persistent 進(jìn)程,即非系統(tǒng)進(jìn)程,必須是空進(jìn)程,即進(jìn)程中沒(méi)有任何 activity 存在。如果殺死存在 Activity 的進(jìn)程,有可能關(guān)閉用戶正在使用的程序,或者使應(yīng)用程序恢復(fù)的時(shí)延變大,從而影響用戶體驗(yàn);必須無(wú) broadcast receiver。運(yùn)行 broadcast receiver 一般都在等待一個(gè)事件的發(fā)生,用戶并不希望此類程序被系統(tǒng)強(qiáng)制關(guān)閉;進(jìn)程中 service 的數(shù)量必須為 0。存在 service 的進(jìn)程很有可能在為一個(gè)或者多個(gè)程序提供某種服務(wù),如 GPS 定位服務(wù)。殺死此類進(jìn)程將使其他進(jìn)程無(wú)法正常服務(wù)。
步驟三,再次檢查當(dāng)前運(yùn)行的進(jìn)程,如果 mRemovedProcesses.size() 仍然大于 curMaxProcs,則放寬條件再次進(jìn)行回收。
步驟四,上面 3 個(gè)過(guò)程都是針對(duì)整個(gè) process 進(jìn)行的資源回收。在以上過(guò)程執(zhí)行完畢之后,將在更小的粒度上對(duì) Activity 的資源進(jìn)行回收。與上面所述類似,列表 mLRUActivities 存儲(chǔ)了當(dāng)前所有運(yùn)行中的 Activity,排序規(guī)則同樣為最少訪問(wèn)原則。mLRUActivities.size() 返回系統(tǒng)中運(yùn)行的 Activity 的數(shù)量,當(dāng)其大于 MAX_ACTIVITIES(MAX_ACTIVITIES 是一個(gè)常量,一般值為 20,代表系統(tǒng)中最大允許同時(shí)存在的 Activity)時(shí)。將回收部分滿足條件的 Activity 以減少內(nèi)存的使用。 這里回收的只是 Activity 的內(nèi)存資源,并不會(huì)殺死進(jìn)程,也不會(huì)影響進(jìn)程的運(yùn)行。當(dāng)進(jìn)程需要調(diào)用被殺掉的 Activity 時(shí),可以從保存的狀態(tài)中回復(fù),當(dāng)然可能需要相對(duì)長(zhǎng)一點(diǎn)的時(shí)延。
Linux 內(nèi)核中的內(nèi)存回收
lowmemorykiller
trimApplications() 函數(shù)中會(huì)執(zhí)行一個(gè)叫做 updateOomAdjLocked() 的函數(shù),如果返回 false,則執(zhí)行默認(rèn)回收,若返回 true 則不執(zhí)行默認(rèn)內(nèi)存回收。
updateOomAdjLocked 將針對(duì)每一個(gè)進(jìn)程更新一個(gè)名為 adj 的變量,并將其告知 Linux 內(nèi)核,內(nèi)核維護(hù)一個(gè)包含 adj 的數(shù)據(jù)結(jié)構(gòu)(即進(jìn)程表),并通過(guò) lowmemorykiller 檢查系統(tǒng)內(nèi)存的使用情況,在內(nèi)存不足的情況下殺死一些進(jìn)程并釋放內(nèi)存。
由于 Android 操作系統(tǒng)中的所有應(yīng)用程序都運(yùn)行在獨(dú)立的 Dalvik 虛擬機(jī)環(huán)境中,Linux 內(nèi)核無(wú)法獲知每個(gè)進(jìn)程的運(yùn)行狀態(tài),也就無(wú)法為每個(gè)進(jìn)程維護(hù)一個(gè)合適的 adj 值,因此,Android Application Framework 中必須提供一套機(jī)制以動(dòng)態(tài)的更新每個(gè)進(jìn)程的 adj。這就是 updateOomAdjLocked()。
Android 基于進(jìn)程中運(yùn)行的組件及其狀態(tài)規(guī)定了默認(rèn)的五個(gè)回收優(yōu)先級(jí):
IMPORTANCE_FOREGROUND:
IMPORTANCE_VISIBLE:
IMPORTANCE_SERVICE:
IMPORTANCE_BACKGROUND:
IMPORTANCE_EMPTY:
【Android操作系統(tǒng)的內(nèi)存回收的策略是什么】相關(guān)文章:
Java內(nèi)存回收07-17
關(guān)于android操作系統(tǒng)05-30
FBD內(nèi)存是什么及作用07-05
操作系統(tǒng)是什么原理06-28
服務(wù)器內(nèi)存是什么09-16
Vista操作系統(tǒng)還原后占內(nèi)存問(wèn)題的解決方法09-06
操作系統(tǒng)多用戶是什么意思02-09
Windows內(nèi)存診斷07-07