Android 服務(wù)為啥保不活

轉(zhuǎn)發(fā)請(qǐng)注明出處:http://www.reibang.com/p/bf0c82be9b25
請(qǐng)尊重原創(chuàng)作者


有一段時(shí)間都在說服務(wù)怎么蓖凭瑁活,怎么才能不被殺死侧啼,各種花里胡哨的迸F猓活方案抄來抄去,到頭來 能打的 一個(gè)都沒有痊乾。

硬核場(chǎng)景
既然這么多可操作性低的“保命方案”皮壁,那么需要知道些什么知識(shí)點(diǎn)才能脫穎而出,好吧我們提供不了蹦纳螅活的黑科技蛾魄,如果對(duì)方按套路出牌的話,至少會(huì)讓你解釋下為什么保不活协饲。

GC
就是因?yàn)镚C機(jī)制畏腕,所以我們的服務(wù)才保不活,但是這個(gè)過程我們不可控茉稠,很難讓運(yùn)行中的應(yīng)用感知什么時(shí)候GC觸發(fā)了描馅,從而做點(diǎn)什么來補(bǔ)救。所以才有了 輪詢機(jī)制 來喚醒而线,一段時(shí)間檢查下服務(wù)有沒有在跑铭污,沒有就再扶起來繼續(xù)送。

通常情況下膀篮,觸發(fā)GC的條件有兩個(gè):
1.當(dāng)應(yīng)用程序空閑時(shí),即沒有應(yīng)用線程在運(yùn)行時(shí),GC會(huì)被調(diào)用(隨心隨意收垃圾)
2.Java堆內(nèi)存不足時(shí),GC會(huì)被調(diào)用(被強(qiáng)制叫去收垃圾)

D/dalvikvm: GC_CONCURRENT freed 2012K, 63% free 3213K/9291K, external 4501K/5161K, paused 2ms+2ms

各參數(shù)對(duì)照含義
D/dalvikvm: <GC_Reason> <Amount_freed>, <Heap_stats>, <External_memory_stats>, <Pause_time>

相信大家都很熟悉這log嘹狞,但對(duì)它表達(dá)的意義估計(jì)就看不太懂,為了方便解釋誓竿,把各參數(shù)對(duì)照在上面列出磅网,簡(jiǎn)單說個(gè)參數(shù),其它大家再去詳細(xì)了解GC的參數(shù)解讀吧筷屡。

GC Reason 就是指引起GC原因涧偷,有以下幾種:

  • GC_CONCURRENT:當(dāng)堆開始填充時(shí)簸喂,并發(fā)GC可以釋放內(nèi)存。
  • GC_FOR_MALLOC:當(dāng)堆內(nèi)存已滿時(shí)燎潮,app嘗試分配內(nèi)存而引起的GC喻鳄,系統(tǒng)必須停止app并回收內(nèi)存。
  • GC_HPROF_DUMP_HEAP:當(dāng)你請(qǐng)求創(chuàng)建 HPROF 文件來分析堆內(nèi)存時(shí)出現(xiàn)- 的GC确封。
  • GC_EXPLICIT:顯示的GC除呵,例如調(diào)用System.gc()(應(yīng)該避免調(diào)用顯示的GC,信任GC會(huì)在需要時(shí)運(yùn)行)爪喘。
  • GC_EXTERNAL_ALLOC:僅適用于 API 級(jí)別小于等于10 颜曾,用于外部分配內(nèi)存的GC。

回到正題腥放,GC為什么導(dǎo)致服務(wù)保不活泛啸?那是因?yàn)樵诋?dāng)各種情況下觸發(fā)了垃圾回收,它就會(huì)去找能宰的都宰掉秃症,從而擠出內(nèi)存給那些優(yōu)先給用戶接觸到的應(yīng)用或服務(wù)。所以才會(huì)有 Notification的前臺(tái)服務(wù) 這樣的做法讓服務(wù)不輕易被殺死吕粹,盡可能把服務(wù)提升靠近用戶种柑,但是其核心思想都是為了改變 oom_adj 的等級(jí),等級(jí)越低越重要越不容易被殺死匹耕。在解釋改變等級(jí)之前聚请,有個(gè)等級(jí)的概念需要先了解的。

進(jìn)程等級(jí)
還是大家熟知的知識(shí)點(diǎn)稳其,進(jìn)程等級(jí)可以劃分為這五大類:
1.前臺(tái)進(jìn)程
2.可見進(jìn)程
3.服務(wù)進(jìn)程
4.后臺(tái)進(jìn)程
5.空進(jìn)程

他們?cè)诓煌瑘?chǎng)景下驶赏,會(huì)對(duì)應(yīng)到某一個(gè)值,具體查看方法可以用 adb 的命令查看既鞠。但這還只是等級(jí)概念煤傍,能大概地估算被殺死的可能性。而最終決定會(huì)不會(huì)被殺的是一個(gè)叫做 閥值 概念的值嘱蛋,這就涉及到 linux 的知識(shí)點(diǎn)蚯姆,我們只需要知道 linux 會(huì)通過某個(gè)計(jì)算方式得出一個(gè)叫做 oom_score 的值,而這個(gè)就是和GC有直接關(guān)系了洒敏,因?yàn)楦鶕?jù)不同情況龄恋,GC回收的程度不一樣,那么每個(gè)等級(jí)都有對(duì)應(yīng)閥值凶伙,只要沒超過這個(gè)閥值的進(jìn)程郭毕,就不會(huì)被回收。

比如說函荣,這次GC只宰到 “后臺(tái)進(jìn)程” 的最低閥值显押,那么 “空進(jìn)程”扳肛、“后臺(tái)進(jìn)程” 都會(huì)被宰,而 [服務(wù)進(jìn)程]煮落、[可見進(jìn)程]敞峭、[前臺(tái)進(jìn)程] 這些進(jìn)程安然無事,但某一時(shí)機(jī)這個(gè)閥值被系統(tǒng)調(diào)得更嚴(yán)格蝉仇,需要更多內(nèi)存了旋讹,調(diào)到 “服務(wù)進(jìn)程” 的最低閥值,那么按照這個(gè)道理轿衔, “空進(jìn)程”沉迹、“后臺(tái)進(jìn)程” 、“服務(wù)進(jìn)程” 都會(huì)被宰掉害驹。好鞭呕,那么我們平時(shí)怎么知道自己的服務(wù)在什么等級(jí)呢?

oom_adj

adj級(jí)別 解釋
UNKNOWN_ADJ 16 預(yù)留的最低級(jí)別宛官,一般對(duì)于緩存的進(jìn)程才有可能設(shè)置成這個(gè)級(jí)別
CACHED_APP_MAX_ADJ 15 緩存進(jìn)程葫松,空進(jìn)程,在內(nèi)存不足的情況下就會(huì)優(yōu)先被kill
CACHED_APP_MIN_ADJ 9 緩存進(jìn)程底洗,也就是空進(jìn)程
SERVICE_B_ADJ 8 不活躍的進(jìn)程
PREVIOUS_APP_ADJ 7 切換進(jìn)程
HOME_APP_ADJ 6 與Home交互的進(jìn)程
SERVICE_ADJ 5 有Service的進(jìn)程
HEAVY_WEIGHT_APP_ADJ 4 高權(quán)重進(jìn)程
BACKUP_APP_ADJ 3 正在備份的進(jìn)程
PERCEPTIBLE_APP_ADJ 2 可感知的進(jìn)程腋么,比如那種播放音樂
VISIBLE_APP_ADJ 1 可見進(jìn)程
FOREGROUND_APP_ADJ 0 前臺(tái)進(jìn)程
PERSISTENT_SERVICE_ADJ -11 重要進(jìn)程
PERSISTENT_PROC_ADJ -12 核心進(jìn)程
SYSTEM_ADJ -16 系統(tǒng)進(jìn)程
NATIVE_ADJ -17 系統(tǒng)起的Native進(jìn)程

在終端輸入命令(過程就大概是 先連接設(shè)備;進(jìn)入shell亥揖;獲得進(jìn)程pid珊擂;查看值)
adb shell
cat /proc/{pid}/oom_adj


查看oom_adj的終端命令

如圖所示了,某一個(gè)進(jìn)程等級(jí)在 -13 那么對(duì)照到上面的表费变,可以知道起碼是 系統(tǒng)進(jìn)程 級(jí)別摧扇,那么普通的GC基本是宰不到它的。所以敝科纾活的核心扛稽,就是為了提升這個(gè)等級(jí),類似的思想就有在AndroidManifest.xml的服務(wù)增加 優(yōu)先級(jí)priority 昼激,就盡量在這個(gè)閥值的范圍往上靠庇绽,希望別宰到我。

不過
也不是沒有辦法背壤В活瞧掺,你需要知道一下這幾個(gè)屬性的作用,但有個(gè)前提咯凡傅!要提升到系統(tǒng)級(jí)別辟狈,唯一有效而且安全的做法,就是有 系統(tǒng)簽名 。類似的哼转,每個(gè)品牌每個(gè)主板每個(gè)型號(hào)都有會(huì)它的簽名文件明未,就如平時(shí)我們自己生成的那種 jks、keystore 文件(只不過它們由 platform.x509.pem壹蔓、platform.pk8 這些來生成)趟妥,然后下面這些屬性就能起作用

android:sharedUserId="android.uid.system"
這個(gè)屬性使用應(yīng)該會(huì)比較少,官方對(duì)它的解釋:與其他應(yīng)用程序共享的Linux用戶ID的名稱佣蓉。默認(rèn)情況下披摄,Android為每個(gè)應(yīng)用程序分配了自己唯一的用戶ID。但是勇凭,如果將該屬性設(shè)置為兩個(gè)或多個(gè)應(yīng)用程序相同的值疚膊,它們將共享相同的ID——前提是它們的證書集相同。具有相同用戶ID的應(yīng)用程序可以訪問彼此的數(shù)據(jù)虾标,如果需要寓盗,還可以在相同的進(jìn)程中運(yùn)行。

換言之璧函,你得有系統(tǒng)簽名才能和他們平起平坐傀蚌。

persistent=true
這個(gè)在保活文章出現(xiàn)的頻率就比較高了蘸吓,但是卻不怎么起作用喳张,再來看看官方解釋:應(yīng)用程序是否應(yīng)該一直運(yùn)行—如果應(yīng)該,則為“true”;如果不應(yīng)該美澳,則為“false”。默認(rèn)值為“false”摸航。應(yīng)用程序通常不應(yīng)設(shè)置此標(biāo)志;持久性模式僅適用于某些系統(tǒng)應(yīng)用程序制跟。

通常情況下,我們的包都會(huì)安裝到 data/data/ 目錄下酱虎,而 persistent 需要 system/app 配套使用才會(huì)起效果的雨膨,也就是說應(yīng)用本身就已經(jīng)是系統(tǒng)應(yīng)用,那么這個(gè)屬性才生效读串,才會(huì)在系統(tǒng)啟動(dòng)的時(shí)候拉起有該屬性的應(yīng)用聊记,并且被殺死后能夠重啟應(yīng)用。

那我們?cè)趺打?yàn)證自己的屬性有沒有生效呢恢暖?
adb shell dumpsys meminfo


專業(yè)素養(yǎng)排监,打碼了

看一下自己的應(yīng)用包名有沒有出現(xiàn)在 Persistent 列表就行了,按照網(wǎng)上那些苯芪妫活方式舆床,通常只會(huì)出現(xiàn)在 A Services 、Visible、Foreground 這些列表內(nèi)挨队。

總結(jié)
大家對(duì)服務(wù)為啥保不活谷暮,有了個(gè)整體概念,那么概括成一句話應(yīng)該就是:GC可能會(huì)殺死等級(jí) oom_adj 不太重要的服務(wù)盛垦,而我們所做的一切都是為了提升這個(gè)等級(jí)的值湿弦,讓它不那么輕易被殺死。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腾夯,一起剝皮案震驚了整個(gè)濱河市颊埃,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俯在,老刑警劉巖竟秫,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異跷乐,居然都是意外死亡肥败,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門愕提,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馒稍,“玉大人,你說我怎么就攤上這事浅侨∨耍” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵如输,是天一觀的道長(zhǎng)鼓黔。 經(jīng)常有香客問我,道長(zhǎng)不见,這世上最難降的妖魔是什么澳化? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮稳吮,結(jié)果婚禮上缎谷,老公的妹妹穿的比我還像新娘。我一直安慰自己灶似,他們只是感情好列林,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著酪惭,像睡著了一般希痴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撞蚕,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天润梯,我揣著相機(jī)與錄音,去河邊找鬼。 笑死纺铭,一個(gè)胖子當(dāng)著我的面吹牛寇钉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播舶赔,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼扫倡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了竟纳?” 一聲冷哼從身側(cè)響起撵溃,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锥累,沒想到半個(gè)月后缘挑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桶略,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年语淘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片际歼。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惶翻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鹅心,到底是詐尸還是另有隱情吕粗,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布旭愧,位于F島的核電站颅筋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏输枯。R本人自食惡果不足惜垃沦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望用押。 院中可真熱鬧,春花似錦靶剑、人聲如沸蜻拨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缎讼。三九已至,卻和暖如春坑匠,著一層夾襖步出監(jiān)牢的瞬間血崭,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留夹纫,地道東北人咽瓷。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像舰讹,于是被迫代替她去往敵國(guó)和親茅姜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354