Android App 苯泼牛活之 ADJ 算法

Android開發(fā)中,令人頭疼的惫埽活問題始終纏繞每一個開發(fā)者其馏。如何保證自己的進程不被系統(tǒng)回收呢?首當其沖應該是保證自己進程的優(yōu)先級爆安。

Android系統(tǒng)在運行時叛复,如果遭遇到內存過低,為保證系統(tǒng)穩(wěn)定與流暢,會回收一部分不常用的進程(當然很多三方rom如miui會在電量過低也會回收)褐奥。這個回收過程當然不是隨意回收咖耘,系統(tǒng)需要有一個判斷進程優(yōu)先級的指標,幫助系統(tǒng)判斷哪些資源是優(yōu)先級高需要保留撬码,哪些資源優(yōu)先級比較低需要釋放該資源儿倒。

ADJ就是系統(tǒng)殺死進程的重要指標

本文從linux\Android進程優(yōu)先級:adj分數(shù),淺析一下如何查看adj以及各個adj分數(shù)背后所代表的含義呜笑。

1.ADJ 如何查看

利用adb shell

1.ps | grep 包名  //查看當前app的進程號

2.cat /proc/進程號/oom_adj  //查看當前進程的adj值(早期android和linux使用义桂,現(xiàn)已廢棄,但仍然有效)

3.cat /proc/進程號/oom_score_adj    //這個是新版本的查看adj的命令蹈垢,adj有效值為-1000~1000

2.ADJ的值的各種含義

ADJ級別                    取值 含義

NATIVE_ADJ              -1000   native進程
SYSTEM_ADJ              -900    僅指system_server進程
PERSISTENT_PROC_ADJ     -800    系統(tǒng)persistent進程
PERSISTENT_SERVICE_ADJ  -700    關聯(lián)著系統(tǒng)或persistent進程
FOREGROUND_APP_ADJ      0       前臺進程
VISIBLE_APP_ADJ         100     可見進程
PERCEPTIBLE_APP_ADJ     200     可感知進程慷吊,比如后臺音樂播放
BACKUP_APP_ADJ          300     備份進程
HEAVY_WEIGHT_APP_ADJ    400     重量級進程
SERVICE_ADJ             500     服務進程(A list中的service)
HOME_APP_ADJ            600     Home進程
PREVIOUS_APP_ADJ        700     上一個進程
SERVICE_B_ADJ           800     B List中的Service
CACHED_APP_MIN_ADJ      900     不可見進程的adj最小值
CACHED_APP_MAX_ADJ      906     不可見進程的adj最大值

3.ADJ觸發(fā)順序

ADJ是一種算法,用于系統(tǒng)判斷進程優(yōu)先級以觸發(fā)Linux的LMK(LowMemoryKill)機制曹抬。一般觸發(fā)時機(Linux下)是在系統(tǒng)低內存時溉瓶,為了維護正在運行的進程,殺掉優(yōu)先級比較低(adj值比較高)的其他進程谤民。

在Android中這一機制有所改動堰酿。在ActivityManagerService里有具體的計算Adj值的源碼。

進程剛啟動時ADJ等于INVALID_ADJ张足,當執(zhí)行完attachApplication()触创,該該進程的curAdj和setAdj不相等,則會觸發(fā)執(zhí)行setOomAdj()將該進程的節(jié)點/proc/pid/oom_score_adj寫入oomadj值为牍。下圖參數(shù)為Android原生閾值哼绑,當系統(tǒng)剩余空閑內存低于某閾值(比如147MB),則從ADJ大于或等于相應閾值(比如900)的進程中碉咆,選擇ADJ值最大的進程抖韩,如果存在多個ADJ相同的進程,則選擇內存最大的進程疫铜。 如下是64位機器茂浮,LMK默認閾值圖:

----------ADJ----------------Memory Left------------
FOREGROUND_APP_ADJ(0)          73MB
VISIBLE_APP_ADJ(100)           92MB
PERCEPTIBLE_APP_ADJ(200)       110MB
BACKUP_APP_ADJ(300)            129MB
CACHED_APP_MIN_ADJ(900)        221MB
CACHED_APP_MAX_ADJ(906)        332MB

4.高級進程 ADJ<0的進程

1.NATIVE_ADJ(-1000):是由init進程fork出來的Native進程,并不受system管控壳咕;

2.SYSTEM_ADJ(-900):是指system_server進程席揽;

3.PERSISTENT_PROC_ADJ(-800): 是指在AndroidManifest.xml中申明android:persistent=”true”的系統(tǒng)(即帶有FLAG_SYSTEM標記)進程,persistent進程一般情況并不會被殺谓厘,即便被殺或者發(fā)生Crash系統(tǒng)會立即重新拉起該進程幌羞。

4.PERSISTENT_SERVICE_ADJ(-700):是由startIsolatedProcess()方式啟動的進程,或者是由system_server或者persistent進程所綁定(并且?guī)в蠦IND_ABOVE_CLIENT或者BIND_IMPORTANT)的服務進程

5.總結

Android進程優(yōu)先級ADJ的每一個ADJ級別往往都有多種場景庞呕,使用adjType完美地區(qū)分相同ADJ下的不同場景新翎; 不同ADJ進程所對應的schedGroup不同程帕,從而分配的CPU資源也不同,schedGroup大體分為TOP(T)地啰、前臺(F)愁拭、后臺(B); ADJ跟AMS中的procState有著緊密的聯(lián)系亏吝。

1.adj:通過調整oom_score_adj來影響進程壽命(Lowmemorykiller殺進程策略)岭埠;

2.schedGroup:影響進程的CPU資源調度與分配;

3.procState:從進程所包含的四大組件運行狀態(tài)來評估進程狀態(tài)蔚鸥,影響framework的內存控制策略惜论。比如控制緩存進程和空進程個數(shù)上限依賴于procState,再比如控制APP執(zhí)行handleLowMemory()的觸發(fā)時機等止喷。
為了說明整體關系馆类,以ADJ為中心來講解跟adjType,schedGroup,procState的對應關系,下面以一幅圖來詮釋整個ADJ算法的精髓弹谁,幾乎涵蓋了ADJ算法調整的絕大多數(shù)場景乾巧。

image

6.最后,開發(fā)時應注意:

1.UI進程與Service進程一定要分離预愤,因為對于包含activity的service進程沟于,一旦進入后臺就成為”cch-started-ui-services”類型的cache進程(ADJ>=900),隨時可能會被系統(tǒng)回收植康;而分離后的Service進程服務屬于SERVICE_ADJ(500)旷太,被殺的可能性相對較小。尤其是系統(tǒng)允許自啟動的服務進程必須做UI分離销睁,避免消耗系統(tǒng)較大內存供璧。
只有真正需要用戶可感知的應用,才調用startForegroundService()方法來啟動前臺服務榄攀,此時ADJ=PERCEPTIBLE_APP_ADJ(200)嗜傅,常駐內存,并且會在通知欄常駐通知提醒用戶檩赢,比如音樂播放,地圖導航违寞。切勿為了常駐而濫用前臺服務贞瞒,這會嚴重影響用戶體驗。

2.進程中的Service工作完成后趁曼,務必主動調用stopService或stopSelf來停止服務军浆,避免占據(jù)內存,浪費系統(tǒng)資源挡闰;

3.不要長時間綁定其他進程的service或者provider乒融,每次使用完成后應立刻釋放掰盘,避免其他進程常駐于內存;

4.APP應該實現(xiàn)接口onTrimMemory()和onLowMemory()赞季,根據(jù)TrimLevel適當?shù)貙⒎潜仨殐却嬖诨卣{方法中加以釋放愧捕。當系統(tǒng)內存緊張時會回調該接口,減少系統(tǒng)卡頓與殺進程頻次申钩。

5.減少在贝位妫活上花心思,更應該在優(yōu)化內存上下功夫撒遣,因為在相同ADJ級別的情況下邮偎,系統(tǒng)會選擇優(yōu)先殺內存占用的進程。

原文:https://blog.csdn.net/zhangbijun1230/article/details/81347749

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末义黎,一起剝皮案震驚了整個濱河市禾进,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌廉涕,老刑警劉巖泻云,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異火的,居然都是意外死亡壶愤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門馏鹤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來征椒,“玉大人,你說我怎么就攤上這事湃累〔龋” “怎么了?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵治力,是天一觀的道長蒙秒。 經(jīng)常有香客問我,道長宵统,這世上最難降的妖魔是什么晕讲? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮马澈,結果婚禮上瓢省,老公的妹妹穿的比我還像新娘。我一直安慰自己痊班,他們只是感情好勤婚,可當我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涤伐,像睡著了一般馒胆。 火紅的嫁衣襯著肌膚如雪缨称。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天祝迂,我揣著相機與錄音睦尽,去河邊找鬼。 笑死液兽,一個胖子當著我的面吹牛骂删,可吹牛的內容都是我干的。 我是一名探鬼主播四啰,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼宁玫,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柑晒?” 一聲冷哼從身側響起欧瘪,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匙赞,沒想到半個月后佛掖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡涌庭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年芥被,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坐榆。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡拴魄,死狀恐怖,靈堂內的尸體忽然破棺而出席镀,到底是詐尸還是另有隱情匹中,我是刑警寧澤,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布豪诲,位于F島的核電站顶捷,受9級特大地震影響,放射性物質發(fā)生泄漏屎篱。R本人自食惡果不足惜服赎,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望交播。 院中可真熱鬧专肪,春花似錦、人聲如沸堪侯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伍宦。三九已至芽死,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間次洼,已是汗流浹背关贵。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卖毁,地道東北人揖曾。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像亥啦,于是被迫代替她去往敵國和親炭剪。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內容