在Android開發(fā)中我們常常遇到app在后臺(tái)長期不使用時(shí)被系統(tǒng)自動(dòng)回收掉,Android系統(tǒng)是怎么實(shí)現(xiàn)這個(gè)功能的呢。我們不討論如何讓app保活的方法挺邀,主要來說說系統(tǒng)實(shí)現(xiàn)這一機(jī)制的原理
1、描述進(jìn)程的重要程度——oom_adj
在Android系統(tǒng)中使用oom_adj值來描述一個(gè)進(jìn)程的重要程度跳座,它是AMS的Process類型中的一個(gè)變量端铛,oom_adj值越小,表示進(jìn)程越重要疲眷,越不容易被殺掉禾蚕。以下是AMS中定義的一些oom_adj值
static final int EMPTY_APP_ADJ;
static final int HIDDEN_APP_MAX_ADJ;
static final int HIDDEN_APP_MIN_ADJ;
static final int HOME_APP_ADJ;
static final int BACKUP_APP_ADJ;
static final int SECONDARY_SERVER_ADJ;
static final int HEAVY_WEIGHT_APP_ADJ;
static final int PERCEPTIBLE_APP_ADJ;
static final int VISIBLE_APP_ADJ;
static final int FOREGROUND_APP_ADJ;
static final int CORE_SERVER_ADJ = -12;
static final int SYSTEM_ADJ = -16;
可以看到一些運(yùn)行核心服務(wù)的進(jìn)程的oom_adj為-12(CORE_SERVER_ADJ),這類進(jìn)程基本不會(huì)被殺死狂丝。其他未賦值的都在static塊中進(jìn)行了初始化换淆,是通過system/rootdir/init.rc進(jìn)行配置的:
# Define the oom_adj values for the classes of processes that can be
# killed by the kernel. These are used in ActivityManagerService.
setprop ro.FOREGROUND_APP_ADJ 0
setprop ro.VISIBLE_APP_ADJ 1
setprop ro.SECONDARY_SERVER_ADJ 2
setprop ro.HIDDEN_APP_MIN_ADJ 7
setprop ro.CONTENT_PROVIDER_ADJ 14
setprop ro.EMPTY_APP_ADJ 15
# Define the memory thresholds at which the above process classes will
# be killed. These numbers are in pages (4k).
setprop ro.FOREGROUND_APP_MEM 1536
setprop ro.VISIBLE_APP_MEM 2048
setprop ro.SECONDARY_SERVER_MEM 4096
setprop ro.HIDDEN_APP_MEM 5120
setprop ro.CONTENT_PROVIDER_MEM 5632
setprop ro.EMPTY_APP_MEM 6144
可以看到前臺(tái)進(jìn)程的oom_adj值為0,這類進(jìn)程時(shí)我們正在交互的進(jìn)程几颜,基本也不會(huì)被殺掉倍试;空進(jìn)程對(duì)應(yīng)的值是15,當(dāng)系統(tǒng)內(nèi)存不足是最新殺掉的就是這類進(jìn)程(這類進(jìn)程一般指的是所有的activity都destory掉了蛋哭,并且沒有service在運(yùn)行)县习。adj值下面描述的是各種內(nèi)存閥值。比如當(dāng)系統(tǒng)剩余內(nèi)存小于6144 * 4kb(ro.EMPTY_APP_MEM)是emty 進(jìn)程就會(huì)被回收掉谆趾。這些值對(duì)與每個(gè)手機(jī)廠商生產(chǎn)的手機(jī)都是不一樣的躁愿。以下是oom_adj值對(duì)應(yīng)的內(nèi)存閥值
0 1536
1 2048
2 4096
7 5120
14 5632
15 6144
如上所說,當(dāng)系統(tǒng)內(nèi)存小于6144 * 4kb時(shí)empty進(jìn)程將會(huì)被回收掉沪蓬,而empty進(jìn)程的oom_adj值為15攘已。在Activity、service怜跑、contentProvider、Broadcast Android四大組件的狀態(tài)的變化都會(huì)導(dǎo)致AMS更新對(duì)應(yīng)進(jìn)程oom_adj值吠勘,所以前臺(tái)進(jìn)程比后臺(tái)進(jìn)程更不容易殺掉性芬,帶有service的后臺(tái)進(jìn)程比沒有service的進(jìn)程更不容易被殺掉
2、LMK
LMK的全稱是low memory killer剧防,它是內(nèi)核的一個(gè)模塊植锉。它里面保存了各個(gè)進(jìn)程的pid以及對(duì)應(yīng)的oom_adj,每次AMS調(diào)用updateOOmAdj函數(shù)更新進(jìn)程的oom_adj時(shí)都會(huì)通知LMK模塊峭拘。
LMK通過linux的shrinker模塊來監(jiān)聽系統(tǒng)的內(nèi)存變化俊庇,當(dāng)系統(tǒng)的剩余內(nèi)存達(dá)到某個(gè)閥值時(shí)就會(huì)殺掉oom_adj值大于這個(gè)閥值對(duì)應(yīng)的oom_adj的進(jìn)程狮暑。它會(huì)優(yōu)先殺掉內(nèi)存占用多的進(jìn)程,如果殺掉這些進(jìn)程內(nèi)存回到了正常值將不會(huì)繼續(xù)殺進(jìn)程辉饱。所以讓app不要占用大量的內(nèi)存也可以起到卑崮校活的作用