偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Android進(jìn)程絕殺技--forceStop

開發(fā) 開發(fā)工具
話說Android開源系統(tǒng)擁有著App不計(jì)其數(shù),百家爭鳴,都想在這“大爭之世”尋得系統(tǒng)存活的一席之地。然則系統(tǒng)資源有限,如若都割據(jù)為王,再強(qiáng)勁的CPU也會(huì)忙不過來,再龐大的內(nèi)存終會(huì)消耗殆盡,再大容量的電池續(xù)航終會(huì)曇花一現(xiàn)。

 一.概述

1.1 引言

話說Android開源系統(tǒng)擁有著App不計(jì)其數(shù),百家爭鳴,都想在這“大爭之世”尋得系統(tǒng)存活的一席之地。然則系統(tǒng)資源有限,如若都割據(jù)為王,再強(qiáng)勁的CPU也會(huì)忙不過來,再龐大的內(nèi)存終會(huì)消耗殆盡,再大容量的電池續(xù)航終會(huì)曇花一現(xiàn)。

面對蕓蕓眾生,無盡變數(shù),系統(tǒng)以不變應(yīng)萬變,一招絕殺神技forceStop騰空出世,此處以adb指令的方式為例來說說其內(nèi)部機(jī)理:

force-stop命令殺掉所有用戶空間下的包名pkgName相關(guān)的信息,也可以通過--user來指定用戶Id。 當(dāng)執(zhí)行上述am指令時(shí),則會(huì)觸發(fā)調(diào)用Am.java的main()方法,接下來從main方法開始說起。

1.2 Am.main

[-> Am.java]

1.3 Am.run

[-> Am.java]

1.4 Am.onRun

[-> Am.java]

1.***m.runForceStop

[-> Am.java]

當(dāng)不指定userId時(shí),則默認(rèn)為UserHandle.USER_ALL。

1.6 AMP.forceStopPackage

[-> ActivityManagerNative.java ::AMP]

1.7 AMN.onTransact

[-> ActivityManagerNative.java]

MP.forceStopPackage來運(yùn)行在執(zhí)行adb時(shí)所創(chuàng)建的進(jìn)程,經(jīng)過Binder Driver后,進(jìn)入system_server進(jìn)程的一個(gè)binder線程來執(zhí)行AMN.forceStopPackage,從這開始的操作(包括當(dāng)前操作)便都運(yùn)行在system_server系統(tǒng)進(jìn)程。

1.8 小節(jié)

進(jìn)程絕殺技force-stop,并非任意app可直接調(diào)用, 否則App間可以相互停止對方,則豈非天下大亂。該方法的存在便是供系統(tǒng)差遣。一般地,點(diǎn)擊home彈出的清理用戶最近使用app采取的策略便是force-stop.

至于force-stop的觸發(fā)方式,除了adb的方式,還可通過獲取ActivityManager再調(diào)用其方法forceStopPackage(),不過這是@hide隱藏方法,同樣是需要具有FORCE_STOP_PACKAGES權(quán)限。雖然第三方普通app不能直接調(diào)用,但對于深入理解Android,還是很有必要知道系統(tǒng)是如何徹底清理進(jìn)程的過程。接下來,進(jìn)入AMS來深入探查force-stop的內(nèi)部機(jī)理。

二. force-stop內(nèi)部機(jī)理

2.1 AMS.forceStopPackage

[-> ActivityManagerService.java]

這里有一個(gè)過程非常重要,那就是setPackageStoppedState()將包的狀態(tài)設(shè)置為stopped,那么所有廣播都無法接收,除非帶有標(biāo)記FLAG_INCLUDE_STOPPED_PACKAGES的廣播,系統(tǒng)默認(rèn)的廣播幾乎都是不帶有該標(biāo)志,也就意味著被force-stop的應(yīng)用是無法通過建立手機(jī)網(wǎng)絡(luò)狀態(tài)或者亮滅的廣播來拉起進(jìn)程。

當(dāng)使用force stop方式來結(jié)束進(jìn)程時(shí), reason一般都是”from pid “ + callingPid. 當(dāng)然也有另外,那就是AMS.clearApplicationUserData方法調(diào)用forceStopPackageLocked的reason為”clear data”.

2.2 AMS.forceStopPackageLocked

清理跟該包名相關(guān)的進(jìn)程和四大組件之外,還會(huì)發(fā)送廣播ACTION_PACKAGE_RESTARTED,用于清理已注冊的alarm,notification信息。

2.3 AMS.forceStopPackageLocked

對于didSomething只指當(dāng)方法中所有行為,則返回true.比如killPackageProcessesLocked(),只要?dú)⑦^一個(gè)進(jìn)程則代表didSomething為true.

該方法的主要功能:

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所涉及的廣播

接下來,從這5個(gè)角度來分別說說force-stop的執(zhí)行過程.

三. Process

3.1 AMS.killPackageProcessesLocked

一般地force-stop會(huì)指定包名,該方法會(huì)遍歷當(dāng)前所有運(yùn)行中的進(jìn)程mProcessNames,以下條件同時(shí)都不滿足的進(jìn)程,則會(huì)成為被殺的目標(biāo)進(jìn)程:(也就是說滿足以下任一條件都可以免死)

persistent進(jìn)程:

進(jìn)程setAdj < minOomAdj(默認(rèn)為-100):

非UserHandle.USER_ALL同時(shí), 且進(jìn)程的userId不相等:多用戶模型下,不同用戶下不能相互殺;

進(jìn)程沒有依賴該packageName, 且進(jìn)程的AppId不相等;

進(jìn)程沒有依賴該packageName, 且該packageName沒有運(yùn)行在該進(jìn)程.

通俗地來說就是:

forceStop不殺系統(tǒng)persistent進(jìn)程;

當(dāng)指定用戶userId時(shí),不殺其他用戶空間的進(jìn)程;

除此之外,以下情況則必然會(huì)成為被殺進(jìn)程:

進(jìn)程已標(biāo)記remove=true的進(jìn)程,則會(huì)被殺;

進(jìn)程的pkgDeps中包含該packageName,則會(huì)被殺;

進(jìn)程的pkgList中包含該packageName,且該進(jìn)程與包名所指定的AppId相等則會(huì)被殺;

進(jìn)程的pkgList是在啟動(dòng)組件或者創(chuàng)建進(jìn)程的過程向該隊(duì)列添加的,代表的是該應(yīng)用下有組件運(yùn)行在該進(jìn)程。那么pkgDeps是指該進(jìn)程所依賴的包名,調(diào)用ClassLoader的過程添加。

3.2 AMS.removeProcessLocked

該方法的主要功能:

從mProcessNames, mPidsSelfLocked隊(duì)列移除該進(jìn)程;

移除進(jìn)程啟動(dòng)超時(shí)的消息PROC_START_TIMEOUT_MSG;

調(diào)用app.kill()來殺進(jìn)程會(huì)同時(shí)調(diào)用Process.kill和Process.killProcessGroup, 該過程詳見理解殺進(jìn)程的實(shí)現(xiàn)原理

調(diào)用handleAppDiedLocked()來清理進(jìn)程相關(guān)的信息, 該過程詳見binderDied()過程分析

四. Activity

4.1 ASS.finishDisabledPackageActivitiesLocked

[-> ActivityStackSupervisor.java]

4.2 AS.finishDisabledPackageActivitiesLocked

[-> ActivityStack.java]

4.3 AS.finishActivityLocked

[-> ActivityStack.java]

4.3.1 AR.makeFinishingLocked

[-> ActivityRecord.java]

4.3.2 ASS.requestVisibleBehindLocked

4.3.3 TaskRecord.setFrontOfTask

[-> TaskRecord.java]

將該Task中從底部往上查詢, ***個(gè)處于非finishing狀態(tài)的ActivityRecord,則設(shè)置為根Activity(即r.frontOfTask = true),其他都為false;

當(dāng)所有的activity都處于finishing狀態(tài),則把***部的activity設(shè)置成跟Activity.

4.3.4 AS.adjustFocusedActivityLocked

[-> ActivityStack.java]

4.3.***S.finishCurrentActivityLocked

 

滿足下面其中之一的條件,則會(huì)執(zhí)行finish以及destroy Activity.

模式為FINISH_IMMEDIATELY

模式為FINISH_AFTER_PAUSE, 且Activity狀態(tài)已處于PAUSED;

Activity的狀態(tài)為STOPPED或INITIALIZING.

4.3.6 AS.destroyActivityLocked

五. Service

5.1 bringDownDisabledPackageServicesLocked

[-> ActiveServices.java]

5.2 collectPackageServicesLocked

[-> ActiveServices.java]

該方法的主要功能就是收集該滿足條件service放入mTmpCollectionResults.

5.3 bringDownServiceLocked

[-> ActiveServices.java]

5.4 unscheduleServiceRestartLocked

六. Provider

6.1 PM.collectPackageProvidersLocked

[-> ProviderMap.java]

當(dāng)userId = UserHandle.USER_ALL時(shí), 則會(huì)mSingletonByClass和mProvidersByClassPerUser結(jié)構(gòu)中查詢所有屬于該package的providers.

當(dāng)userId = UserHandle.USER_OWNER時(shí),則會(huì)從mSingletonByClass和mProvidersByClassPerUser中userId相等的 數(shù)據(jù)結(jié)構(gòu)中查詢所有屬于該package的providers.

當(dāng)userId不屬于上述兩者之一時(shí),則會(huì)從mProvidersByClassPerUser中userId相等的查詢所有屬于該package的providers.

6.2 PM.collectPackageProvidersLocked

[-> ProviderMap.java]

6.3 AMS.removeDyingProviderLocked

當(dāng)其他app使用該provider, 且建立stable的連接, 那么對于非persistent進(jìn)程,則會(huì)由于依賴該provider的緣故而被殺.

七. Broadcast

7.1 BQ.cleanupDisabledPackageReceiversLocked

[-> BroadcastQueue.java]

該方法主要功能:

清理并行廣播隊(duì)列mParallelBroadcasts;

清理有序廣播隊(duì)列mOrderedBroadcasts

7.2 BR.cleanupDisabledPackageReceiversLocked

[-> BroadcastRecord.java]

八. Alarm和Notification

在前面[小節(jié)2.2]介紹到處理完forceStopPackageLocked(),緊接著便是發(fā)送廣播ACTION_PACKAGE_RESTARTED,經(jīng)過Broadcast廣播分發(fā),最終調(diào)用到注冊過該廣播的接收者。

8.1 Alarm清理

[-> AlarmManagerService.java]

調(diào)用AlarmManagerService中的removeLocked()方法,從mAlarmBatches和mPendingWhileIdleAlarms隊(duì)列中移除包所相關(guān)的alarm.

8.2 Notification清理

[-> NotificationManagerService.java]

mNotificationList隊(duì)列中移除包所相關(guān)的Notification.

九. 級聯(lián)誅殺

這里就跟大家分享一段經(jīng)歷吧,記得之前有BAT的某瀏覽器大廠(具體名稱就匿了),瀏覽器會(huì)因?yàn)榱硪粋€(gè)app被殺而導(dǎo)致自己無辜被牽連所殺,并懷疑是ROM定制化導(dǎo)致的bug,于是發(fā)郵件向我廠請教緣由。

遇到這個(gè)問題,首先將兩個(gè)app安裝到Google原生系統(tǒng),結(jié)果是依然會(huì)被級聯(lián)誅殺,很顯然可以排除廠商ROM定制的緣故,按常理說bug應(yīng)該可以讓app自行解決。出于好奇,幫他們進(jìn)一步調(diào)查了下這個(gè)問題,發(fā)現(xiàn)并非無辜被殺,而是force-stop的級聯(lián)誅殺所導(dǎo)致的。

簡單來說就是App1調(diào)用了getClassLoader()來加載App2,那么App1所運(yùn)行的進(jìn)程便會(huì)在其pkgDeps隊(duì)列中增加App2的包名,在前面[小節(jié)3.2]已經(jīng)提到pkgDeps,殺進(jìn)程的過程中會(huì)遍歷該隊(duì)列,當(dāng)App2被forceStop所殺時(shí),便是級聯(lián)誅殺App1。App1既然會(huì)調(diào)用App2的ClassLoader來加載其方法,那么就建立了一定的聯(lián)系,這是Google有意賦予forceStop這個(gè)強(qiáng)力殺的功能。

這個(gè)故事是想告訴大家在插件化或者反射的過程中要注意這種情況,防止不必要的誤傷。接下來具體說說這個(gè)過程是如何建立依賴的。

9.1 CI.getClassLoader

[-> ContextImpl.java]

9.2 LA.getClassLoader

[-> LoadedApk.java]

9.3 AMS.addPackageDependency

調(diào)用ClassLoader來加載啟動(dòng)包名時(shí),則會(huì)將該包名加入到進(jìn)程的pkgDeps。

十. 總結(jié)

forceStop的功能如下:


 

 

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.

功能點(diǎn)歸納:

force-stop并不會(huì)殺persistent進(jìn)程;

當(dāng)app被force-stop后,無法接收到任何普通廣播,那么也就常見的監(jiān)聽手機(jī)網(wǎng)絡(luò)狀態(tài)的變化或者屏幕亮滅的廣播來拉起進(jìn)程肯定是不可行;

當(dāng)app被force-stop后,那么alarm鬧鐘一并被清理,無法實(shí)現(xiàn)定時(shí)響起的功能;

app被force-stop后,四大組件以及相關(guān)進(jìn)程都被一一剪除清理,即便多進(jìn)程架構(gòu)的app也無法拉起自己;

級聯(lián)誅殺:當(dāng)app通過ClassLoader加載另一個(gè)app,則會(huì)在force-stop的過程中會(huì)被級聯(lián)誅殺;

生死與共:當(dāng)app與另個(gè)app使用了share uid,則會(huì)在force-stop的過程,任意一方被殺則另一方也被殺,建立起生死與共的強(qiáng)關(guān)系。

既然force-stop多次提到殺進(jìn)程,那***簡單說兩句關(guān)于?;睿赫_的?;钭藨B(tài),應(yīng)該是在用戶需要時(shí)保證千萬別被殺,用戶不需要時(shí)別強(qiáng)?;?,一切以用戶為出發(fā)點(diǎn)。

進(jìn)程是否需要存活,系統(tǒng)上層有AMS來管理緩存進(jìn)程和空進(jìn)程,底層有LowMemoryKiller來根據(jù)系統(tǒng)可用內(nèi)存的情況來管理進(jìn)程是否存活,這樣的策略是從系統(tǒng)整體性角度考慮,為了是給用戶提供更好更流暢的用戶體驗(yàn)。

用戶需要的時(shí)候千萬別被殺:謹(jǐn)慎使用插件化和共享uid,除非愿意接受級聯(lián)誅殺和生死與共的場景;還有就是提高自身app的穩(wěn)定性,減少crash和anr的發(fā)生頻率,這才是正道。

用戶不需要的時(shí)候別強(qiáng)?;睿簽榱吮;睿噙M(jìn)程架構(gòu),利用各種小技巧來提升優(yōu)先級等都是不可取的,一招force-stop足以干掉90%以上的?;畈呗?,當(dāng)然還有一些其他手段及漏洞來保活,系統(tǒng)層面往往還會(huì)采取一些特別的方法來禁止?;?。博主曾經(jīng)干過手機(jī)底層的性能與功耗優(yōu)化工作,深知不少app的流氓行徑,嚴(yán)重系統(tǒng)的流暢度與手機(jī)續(xù)航能力。

為了Android有更好的用戶體驗(yàn),為了不影響手機(jī)系統(tǒng)性能,為了不降低手機(jī)續(xù)航能力,建議大家花更多時(shí)間精力在如何提高app的穩(wěn)健性,如何優(yōu)化app性能,共同打造Android的良好生態(tài)圈。

【本文是51CTO專欄“小米開放平臺(tái)”原創(chuàng)文章,“小米開放平臺(tái)”微信公眾號xiaomideveloper】

 

責(zé)任編輯:武曉燕 來源: 小米開放平臺(tái)
相關(guān)推薦

2012-06-07 15:51:40

HTML5

2023-05-25 21:32:54

AI蘋果ChatGPT

2017-03-13 15:39:09

Windows 10進(jìn)程必殺技

2023-09-26 07:49:11

AOP代理spring

2017-11-10 12:55:30

分析流量銷量

2016-10-28 21:30:00

AndroidJava進(jìn)程

2024-05-23 08:24:11

Android進(jìn)程開發(fā)

2017-01-10 13:12:00

互聯(lián)網(wǎng)游戲

2010-02-06 10:26:55

Android進(jìn)程

2016-10-10 16:27:23

247 科技

2019-11-21 16:52:48

人工智能宇宙電腦

2011-12-02 13:19:59

AndroidiPhone

2014-12-11 16:40:31

Android|進(jìn)程線程

2010-02-06 10:54:38

Android進(jìn)程

2018-11-16 13:09:39

以色列創(chuàng)新信息

2018-11-07 17:00:06

2012-06-19 15:12:36

歐洲杯iPhone戴爾

2016-04-01 09:32:52

2013-03-28 13:14:45

AIDL進(jìn)程間通信Android使用AI

2011-02-05 08:54:04

Android
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號