本篇文章簡單總結(jié)一下Android系統(tǒng)查殺進(jìn)程的方式务漩。
一、進(jìn)程查殺方式總結(jié)
殺進(jìn)程方法 | 方法所在類 | 使用層 | 方法描述 |
---|---|---|---|
System.exit(int status) | System | 應(yīng)用 | 退出虛擬機(jī)卫漫。status=0為正常退出、非0為異常退出肾砂。 |
Process.killProcess(int pid) | Process | 應(yīng)用列赎、系統(tǒng) | 調(diào)用sendSignal發(fā)送信號9,殺死指定pid進(jìn)程。app調(diào)用只能自殺包吝,系統(tǒng)可以殺掉指定pid進(jìn)程饼煞。 |
Process.killProcessGroup(int uid, int pid) | Process | 系統(tǒng) | 殺掉pid所在的進(jìn)程組內(nèi)的所有進(jìn)程。 |
killApplicationProcess(String processName, int uid) | AMS | 系統(tǒng) | 系統(tǒng)uid應(yīng)用才能調(diào)用诗越,binder call到客戶端自殺:app.thread.scheduleSuicide(); |
killApplication(String pkg, int appId, int userId, String reason) | AMS | 系統(tǒng) | 系統(tǒng)uid應(yīng)用才能調(diào)用砖瞧,會將目標(biāo)應(yīng)用強(qiáng)殺,作用于指定用戶空間。 |
killAllBackgroundProcesses() | AMS | 系統(tǒng) | 需要KILL_BACKGROUND_PROCESS權(quán)限嚷狞,殺死系統(tǒng)所有優(yōu)先級小于等于CACHED進(jìn)程块促。 |
killBackgroundProcesses(final String packageName, int userId, String reason) | AMS | 應(yīng)用、系統(tǒng) | 需要KILL_BACKGROUND_PROCESS權(quán)限床未,殺死指定package所有優(yōu)先級小于等于SERVICE進(jìn)程,作用于指定用戶空間竭翠。 |
killProcessesBelowForeground(String reason) | AMS | 系統(tǒng) | 系統(tǒng)uid應(yīng)用才能調(diào)用,殺死系統(tǒng)所有優(yōu)先級小于FOREGROUND的進(jìn)程薇搁。 |
killPackageDependents(String packageName, int userId) | AMS | 系統(tǒng) | 需要KILL_UID權(quán)限斋扰,殺死指定package所有優(yōu)先級小于等于FOREGROUND進(jìn)程,作用于指定用戶空間。 |
killPids(int[] pids, String pReason, boolean secure) | AMS | 系統(tǒng) | 系統(tǒng)UID應(yīng)用才能調(diào)用啃洋,首先找出所有進(jìn)程所有worstType(跟adj相關(guān)的一個判斷值)传货,殺死小于等于這個優(yōu)先級的進(jìn)程。很保守的查殺方法,并不保證進(jìn)程被殺 |
killUid(int appId, int userId, String reason) | AMS | 應(yīng)用、系統(tǒng) | 需要KILL_UID權(quán)限缅糟,殺死UID下所有進(jìn)程估脆,system_server與native進(jìn)程除外 |
killAppAtUsersRequest(ProcessRecord app, Dialog fromDialog) | AMS | 系統(tǒng) | 系統(tǒng)發(fā)生異常后調(diào)用,例如ANR ,多為用戶主動觸發(fā) |
forceStopPackage(final String packageName, int userId) | AMS | 系統(tǒng) | 需要FORCE_STOP_PACKAGE權(quán)限废累,殺死應(yīng)用所有進(jìn)程,并清除各個進(jìn)程組件信息,作用于指定用戶空間窟勃,強(qiáng)殺之后連根拔起,寸草不生逗堵。屬于終極Kill秉氧。 |
注:AMS對應(yīng)的應(yīng)用層調(diào)用方法在ActivityManager中,通過如下方法獲取ActivityManager來調(diào)用:
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
二蜒秤、進(jìn)程查殺核武器:force stop介紹
2.1 查殺方法:
調(diào)用AMS forceStopPackageLocked(final String packageName, int uid, String reason)
2.2 查殺條件:
- forceStop不殺系統(tǒng)persistent進(jìn)程汁咏;
- 當(dāng)指定用戶userId時,不殺其他用戶空間的進(jìn)程作媚;
除此之外攘滩,以下情況則必然會成為被殺進(jìn)程:
- 進(jìn)程已標(biāo)記remove=true的進(jìn)程,則會被殺纸泡;
- 進(jìn)程的pkgDeps中包含該packageName漂问,則會被殺;
- 進(jìn)程的pkgList中包含該packageName,且該進(jìn)程與包名所指定的AppId相等則會被殺蚤假;
進(jìn)程的pkgList是在啟動組件或者創(chuàng)建進(jìn)程的過程向該隊列添加的栏饮,代表的是該應(yīng)用下有組件運(yùn)行在該進(jìn)程。那么pkgDeps是指該進(jìn)程所依賴的包名磷仰,調(diào)用ClassLoader的過程添加袍嬉。
2.3 查殺過程:
- 應(yīng)用狀態(tài):pms.setPackageStoppedState()將應(yīng)用的狀態(tài)置為STOP,并且無法通過帶有EXCLUDE_STOPPED flag的廣播啟動進(jìn)程
- Process: 調(diào)用AMS.killPackageProcessesLocked()清理該package所涉及的進(jìn)程;
- Activity: 調(diào)用ASS.finishDisabledPackageActivitiesLocked()清理該package所涉及的Activity;
- Service: 調(diào)用AS.bringDownDisabledPackageServicesLocked()清理該package所涉及的Service;
- Provider: 調(diào)用AMS.removeDyingProviderLocked()清理該package所涉及的Provider;
- BroadcastRecevier: 調(diào)用BQ.cleanupDisabledPackageReceiversLocked()清理該package所涉及的廣播
- 發(fā)送廣播ACTION_PACKAGE_RESTARTED灶平,用于停止已注冊的alarm,notification.
當(dāng)app被force-stop后伺通,90%保活策略都會失效:
- 無法接收到任何普通廣播民逼,那么也就常見的監(jiān)聽手機(jī)網(wǎng)絡(luò)狀態(tài)的變化或者屏幕亮滅的廣播來拉起進(jìn)程肯定是不可行泵殴;
- alarm鬧鐘一并被清理,無法實(shí)現(xiàn)定時響起的功能拼苍;
- 四大組件以及相關(guān)進(jìn)程都被一一剪除清理笑诅,即便多進(jìn)程架構(gòu)的app也無法拉起自己;
- 級聯(lián)誅殺:當(dāng)app通過ClassLoader加載另一個app疮鲫,則會在force-stop的過程中會被級聯(lián)誅殺吆你;
- 生死與共:當(dāng)app與另個app使用了share uid,在force-stop的過程俊犯,任意一方被殺則另一方也被殺妇多,建立起生死與共的強(qiáng)關(guān)系。
參考:
http://gityuan.com/2016/10/22/force-stop/
系列文章:
Android進(jìn)程管理篇(一)-應(yīng)用進(jìn)程啟動過程
Android進(jìn)程管理篇(二)-進(jìn)程查殺方式總結(jié)
Android進(jìn)程管理篇(三)-AMS進(jìn)程調(diào)度
lowmemorykiller總結(jié)