本文是 Android 系統(tǒng)學(xué)習(xí)系列文章中的第一章節(jié)第二小節(jié)內(nèi)容炸卑,從源碼出發(fā)說明了 Android 應(yīng)用進(jìn)程是如何啟動(dòng)的亡蓉,經(jīng)過哪些進(jìn)程的通力合作,它們是如何是設(shè)計(jì)的瞳浦。担映。對(duì)此系列感興趣的同學(xué),可以收藏這個(gè)鏈接 Android 系統(tǒng)學(xué)習(xí)叫潦,也可以使用 RSS 進(jìn)行訂閱蝇完。
閱讀的收益
討論的內(nèi)容也就是一個(gè)應(yīng)用進(jìn)程是如何啟動(dòng)的,私以為這一部分的內(nèi)容頗為重要,即便不了解細(xì)節(jié)短蜕,也要知道其中的大體步驟氢架。特別是針對(duì)我們應(yīng)用開發(fā)者而言,理應(yīng)了解我們的 App 是如何被啟動(dòng)的朋魔,App 中的組件是如何被系統(tǒng)服務(wù)調(diào)用和組織的岖研。
講應(yīng)用進(jìn)程啟動(dòng)的文章不是很多,也都沒有說到點(diǎn)上铺厨,大抵都是對(duì)源碼的堆疊缎玫,沒有個(gè)人的理解在里面。如果非要看調(diào)用棧的話解滓,在合適的地方掛上斷點(diǎn),或者通過輸出異常棧的方式都可以看到筝家,如下圖所示洼裤。老羅的文章 Android應(yīng)用程序啟動(dòng)過程源代碼分析 事無巨細(xì),但感覺還是沒有說到點(diǎn)子上溪王,因而這篇文章只做到拋磚引玉的作用腮鞍,希望有更好的文章出現(xiàn)。細(xì)節(jié)是復(fù)雜的莹菱,原理是簡(jiǎn)單的移国,這里盡可能地從原理角度出發(fā)進(jìn)行說明,加深大家的理解道伟。
對(duì)這篇文章閱讀后迹缀,你能了解從用戶點(diǎn)擊 Launcher 上的 App 圖標(biāo),到顯示出 App 界面時(shí)主要發(fā)生的事情蜜徽,而通過對(duì)這個(gè)一過程的了解祝懂,將知曉以下知識(shí)點(diǎn)。
- Android Process 的創(chuàng)建過程拘鞋,以及 Activity Manager Service 是如何參與這個(gè)步驟砚蓬,以及在其中扮演的角色?
- Android 中所謂的主線程是怎么回事盆色?主線程是誰灰蛙?又如何被創(chuàng)建的。
- Android 系統(tǒng)是如何節(jié)省進(jìn)程創(chuàng)建開銷的隔躲?
應(yīng)用進(jìn)程簡(jiǎn)介
在 Android 中每一個(gè)應(yīng)用程序都被設(shè)計(jì)為單獨(dú)的進(jìn)程摩梧,應(yīng)用程序也可以根據(jù)自己的需要去決定是否需要啟用多個(gè)進(jìn)程,不過總而言之都與其他應(yīng)用程序和系統(tǒng)服務(wù)是相互獨(dú)立的蹭越。從解耦和系統(tǒng)穩(wěn)定性的角度上看都應(yīng)該運(yùn)行在不同的進(jìn)程上障本,畢竟不能因?yàn)閼?yīng)用程序的崩潰就影響到其他應(yīng)用進(jìn)程或者系統(tǒng)服務(wù)進(jìn)程。
應(yīng)用進(jìn)程不同于其他 Android 系統(tǒng)中的守護(hù)進(jìn)程,當(dāng)內(nèi)存不夠的時(shí)候驾霜,某些應(yīng)用進(jìn)程可能會(huì)被系統(tǒng)回收掉案训,因而應(yīng)用進(jìn)程也是有其生命周期的,更多信息參考 Android Developer 官網(wǎng)對(duì)于 Process 的教程 粪糙。Android 應(yīng)用組件不一定要運(yùn)行在單獨(dú)的進(jìn)程上强霎,也可以運(yùn)行在多個(gè)進(jìn)程上,通過對(duì) Android 組件指定運(yùn)行的進(jìn)程 android:process
蓉冈,即可讓其運(yùn)行在其他線程上城舞。
每個(gè)應(yīng)用進(jìn)程都相當(dāng)于一個(gè) Sandbox 沙箱,Android 通過對(duì)每一個(gè)應(yīng)用分配一個(gè) UID寞酿,注意這里的 UID 不同于 Linux 系統(tǒng)的 User ID家夺,可以將每個(gè)應(yīng)用理解為一個(gè) User
,只能對(duì)其目錄下的內(nèi)容具有訪問和讀寫權(quán)限伐弹,這樣就從根源上保護(hù)了其他應(yīng)用程序拉馋,下圖說明了其隔離效果。
Zygote 進(jìn)程
Zygote 的中文意思是受精卵惨好,從這個(gè)意思里也可以看出 Zygote 進(jìn)程是用來分裂復(fù)制(fork)的煌茴,實(shí)際上所有的 App 進(jìn)程都是通過對(duì) Zygote 進(jìn)程的 Fork 得來的。當(dāng) app_process 啟動(dòng) Zygote 時(shí)日川,Zygote 會(huì)在其啟動(dòng)后蔓腐,預(yù)加載必要的 Java Classes(相關(guān)列表查看 預(yù)加載文件) 和 Resources,并啟動(dòng) System Server 龄句,并打開 /dev/socket/zygote
socket 去監(jiān)聽啟動(dòng)應(yīng)用程序的請(qǐng)求回论,日后。在下面的代碼中撒璧,顯示了 Zygote 進(jìn)程如何啟動(dòng)透葛,和加載 System Server 的。
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
public static void main(String argv[]) {
// ...
registerZygoteSocket(socketName); // 開啟 Zygote socket.
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(); // 預(yù)加載資源
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// Finish profiling the zygote initialization.
SamplingProfilerIntegration.writeZygoteSnapshot();
// Do an initial gc to clean up after startup
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
gcAndFinalize(); // 觸發(fā) GC
if (startSystemServer) { // 啟動(dòng) System Server.
startSystemServer(abiList, socketName);
}
// ...
}
那么為何要做這種設(shè)計(jì)呢卿樱?每個(gè)應(yīng)用程序的運(yùn)行僚害,都需要依托于相應(yīng)的運(yùn)行環(huán)境,而這個(gè)就是 Davlik (ART) 虛擬機(jī)繁调,但每次啟動(dòng)的開銷較大萨蚕,而通過對(duì) Zygote 進(jìn)程的 Fork,能夠提升不小的效率蹄胰。并且在這個(gè)工程中岳遥,采用了 Copy-on-Write 的方式,極大程度上地復(fù)用了 Zygote 上面的資源裕寨。更多信息也可以參考我這篇博文 詳解 Android 是如何啟動(dòng)的浩蓉。
App 應(yīng)用進(jìn)程啟動(dòng)
接下來的內(nèi)容涉及到很多 Binder 通信相關(guān)的東西派继,因此在閱讀本文前,建議查閱下 Binder 相關(guān)的文章捻艳,這里有下列文章供查考驾窟。
- Android Binder 完全解析(一)概述
- Android Binder 完全解析(二)設(shè)計(jì)詳解
- Android Binder 完全解析(三)AIDL實(shí)現(xiàn)原理分析
ActivityManager 架構(gòu)
在我們編程過程中,涉及到許多 Activity 跳轉(zhuǎn)的事情认轨,在 Launcher 中點(diǎn)擊 Icon 進(jìn)行跳轉(zhuǎn)也是同樣的道理绅络,調(diào)用 context.startActivity(intent)
方法。Launcher 出于一個(gè)線程嘁字,而啟動(dòng)的 App 則運(yùn)行在另一個(gè)進(jìn)程中恩急,在這其中勢(shì)必牽涉到跨進(jìn)程 (IPC) 調(diào)用,這樣復(fù)雜的過程顯然需要一種中介者纪蜒,或者一個(gè)系統(tǒng)來進(jìn)行中轉(zhuǎn)和管理衷恭,而這個(gè)服務(wù)就是 ActivityManagerService
。
ActivityManagerService
作為一個(gè)守護(hù)進(jìn)程運(yùn)行在 Android Framework 中霍掺,如果讓開發(fā)者直接接觸這個(gè)類的話匾荆,就需要開發(fā)者自行處理 IPC 調(diào)用的問題,且這有不利于 Android 系統(tǒng)進(jìn)行安全校驗(yàn)等工作杆烁。因而 Android 系統(tǒng)實(shí)現(xiàn)了 ActivityManager
,通過這個(gè) ActivityManager
作為一個(gè)入口简卧,變相地和 ActivityManagerService
打交道兔魂。這種模式在 Android 系統(tǒng)中極為常見,類似的還有 WifiManager
, LocationManager
举娩,WindowsManager
等等析校。而這些 Manger 在背后調(diào)用的東西就是前面提及的 Binder 機(jī)制。下面以 ActivityManger 為例看看其背后的運(yùn)作方式铜涉。
Binder 體系架構(gòu)可以分為 Client 和 Server 兩端智玻,為了更方便 Client 的調(diào)用,這次采用了 AIDL 的方式芙代,具體參考鏈接 Android Binder 完全解析(三)AIDL實(shí)現(xiàn)原理分析 吊奢。這里再用類比的方式來說明,方便大家理解纹烹。歷史上有不少垂簾聽政的故事页滚,背后操作的人實(shí)際是通過控制傀儡來控制朝政,通過給傀儡皇帝傳遞命令铺呵,傀儡皇帝只是復(fù)述命令裹驰,起到傳遞的作用。更有甚者片挂,不想去上朝的控權(quán)者幻林,會(huì)通過手下的太監(jiān)或者婢女贞盯,轉(zhuǎn)述給傀儡皇上。這種模式被我們稱為代理模式沪饺,ActivityManger
所使用的就是這種模式躏敢。
首先這里要針對(duì)要執(zhí)行的命令進(jìn)行抽象,這樣掌權(quán)者随闽、太監(jiān)父丰、皇上和朝政才能聽懂。IActivityManager
就是對(duì)這個(gè)進(jìn)行的抽象掘宪,點(diǎn)擊查看 源碼蛾扇,這幾種就包括常見的 startActivity, showWaitingForDebugger, finishActivity 等等。ActivityManagerProxy
就相當(dāng)于其他的太監(jiān)或者婢女魏滚,Proxy 不需要懂具體的業(yè)務(wù)镀首,只需要把指令傳遞過去就行。ActivityManagerService
就是具體的執(zhí)行者鼠次,就是大臣們更哄。ActivityManger
則就是具體的業(yè)務(wù)邏輯的外觀類(參加GOF的設(shè)計(jì)模式),也就是具體的掌權(quán)者們腥寇。它們的關(guān)系如下圖所示:
源碼分析從 Launcher 到 ActivityManager 啟動(dòng)步驟
接下來分析下成翩,在源碼里是具體操作的,也驗(yàn)證我們前面的說法赦役。
(1) 點(diǎn)擊 Launcher 的圖標(biāo)麻敌,會(huì)調(diào)用到 Activity 的 startActivity 方法。在繼續(xù)往下看過去掂摔,這個(gè)里面會(huì)調(diào)用到 startActivityForResult 方法术羔,在 startActivityForResult 方法中,疏通同歸乙漓,最后會(huì)調(diào)用 mInstrumentation.execStartActivity
方法级历。
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
if (mParent == null) {
// ### ...
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
} else {
// ### ...
}
}
(2) Instrumentation 執(zhí)行 execStartActivity 方法。參數(shù)里面中的 contextThread 和 token 對(duì)象都是 IBinder 類型叭披,而 Binder 可以在跨進(jìn)程調(diào)用中依舊充當(dāng) Token 的角色寥殖,在多進(jìn)程中由 Binder Driver 保證依然可以是唯一的。
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
// monitor ...
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
}
return null;
}
(3) ActivityManagerNative.getDefault().startActivity趋观。getDefault 中實(shí)際返回的就是 Proxy 對(duì)象扛禽,在實(shí)際中只起到代理的重要,并不進(jìn)行邏輯處理皱坛。
先看看 ActivityManagerNative.getDefault() 中的實(shí)現(xiàn)编曼。
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
IActivityManager 根據(jù)前文的描述即是對(duì)于可操作接口的抽象,Singleton 則是對(duì)單例對(duì)象的封裝剩辟。也就是說 gDefault 返回了實(shí)現(xiàn) IActivityManager 的單例掐场。
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
在 asInterface 中返回了 ActivityManagerProxy, 這就是前文提及的 太監(jiān)和婢女 角色往扔,我們?cè)倏纯?ActivityManagerProxy 內(nèi)部是如何工作的。
(4) ActivityManagerProxy 的實(shí)現(xiàn)熊户。從源碼里面可以看出萍膛,ActivityManagerProxy 將遠(yuǎn)程 Binder 作為構(gòu)造函數(shù)的參數(shù),而在 startActivity 方法中嚷堡,通過遠(yuǎn)程 Binder 對(duì)象的 transact
方法蝗罗,將參數(shù)寫入到 data
中,在遠(yuǎn)程執(zhí)行完畢后蝌戒,結(jié)果寫入到 reply
里串塑。這里實(shí)實(shí)在在地起到了 Proxy 的作用,只負(fù)責(zé)數(shù)據(jù)的傳輸北苟。重點(diǎn)在下面這行代碼:
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
class ActivityManagerProxy implements IActivityManager {
public ActivityManagerProxy(IBinder remote) {
mRemote = remote;
}
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
// other methods.
}
(5) ActivityManagerService 的調(diào)用桩匪。
在上部分提及的 ActivityManagerProxy 中在構(gòu)造函數(shù)里傳入的 mRemote 遠(yuǎn)程Binder 是什么了?答案就在前面提及的 gDefault 里面友鼻。
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
IBinder b = ServiceManager.getService("activity");
上面這段代碼返回的即是 ActivityManagerService
傻昙。所有的系統(tǒng)服務(wù)都是 IBinder 對(duì)象,即他們必須支持遠(yuǎn)程調(diào)用彩扔。而每個(gè)系統(tǒng)服務(wù)都會(huì)通過在 ServiceManager 注冊(cè)別名的方式妆档,告知 ServiceManager 通過相應(yīng)的別名即可訪問到我。而 activity 正是 ActivityManagerService 的別名虫碉。
從 ActivityManagerService 到 進(jìn)程啟動(dòng)
ActivityManagerService 在接受到相應(yīng)的 Intent 請(qǐng)求后(Activity过吻、Broadcast、Service蔗衡、ContentProvider),會(huì)查看是否需要進(jìn)行新建進(jìn)程的工作乳绕,這里以 Activity 為例绞惦,其他組件的步驟與此原理相同,就不再贅述洋措。
(1) ActivityManagerService 在啟動(dòng) Activity 之前济蝉,首先通過 resolveIntent 方法,來得到相應(yīng)的 ResolveInfo菠发,其后通過調(diào)用 startActivityLocked 往下啟動(dòng) Activity王滤。
try {
ResolveInfo rInfo =
AppGlobals.getPackageManager().resolveIntent(
intent, null,
PackageManager.MATCH_DEFAULT_ONLY
| ActivityManagerService.STOCK_PM_FLAGS, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
aInfo = mService.getActivityInfoForUser(aInfo, userId);
} catch (RemoteException e) {
aInfo = null;
}
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options,
componentSpecified, null, container, inTask);
(2) startSpecificActivityLocked 方法,判斷是否需要新建進(jìn)程滓鸠。從代碼中看出雁乡,這里對(duì) ProcessRecord 進(jìn)行了判斷,ProcessRecord 就是響應(yīng)的進(jìn)程記錄糜俗,如果存在相應(yīng)的進(jìn)程踱稍,就啟動(dòng)相應(yīng)的 Activity, 否則將創(chuàng)建進(jìn)程曲饱。mService.startProcessLocked
這個(gè)方法實(shí)現(xiàn)了開啟進(jìn)程,下面再看看里面的實(shí)現(xiàn)珠月。
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.task.stack.setLaunchTime(r);
if (app != null && app.thread != null) {
try {
// ignore some code...
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
(3) startProcessLocked 在內(nèi)部調(diào)用了 Process.start
方法扩淀,并且指定了 android.app.ActivityThread
作為進(jìn)程的入口,進(jìn)程啟動(dòng)后啤挎,將調(diào)用 android.app.ActivityThread
的 main 方法驻谆。
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
// ...
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
checkTime(startTime, "startProcess: asking zygote to start proc");
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
app.info.dataDir, entryPointArgs);
// ...
}
(4) 在 Process.start 方法中,實(shí)際調(diào)用的是 startViaZygote
方法庆聘,在這個(gè)方法里通過 openZygoteSocketIfNeeded 打開 Zygote 的 socket胜臊,并通過 zygoteSendArgsAndGetResult
進(jìn)行交互。
根據(jù)前文提及的內(nèi)容掏觉,zygote 開啟了一個(gè) socket 監(jiān)聽功能区端,監(jiān)聽需要?jiǎng)?chuàng)建 Process 的請(qǐng)求,因而在這里澳腹,我們?nèi)ゲ榭?Zygote 的代碼织盼,看其是怎么監(jiān)聽請(qǐng)求的。
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
(5) ZygoteInit.runSelectLoop 方法酱塔,從源碼的實(shí)現(xiàn)中可以看出沥邻,這里是不斷地取 Socket 建立的鏈接(ZygoteConnection),然后調(diào)用 ZygoteConnection 中的 runOnce 方法羊娃。
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
(6) ZygoteConnection.runOnce 方法里唐全,fork 了 Zygote 進(jìn)程,這就是 應(yīng)用進(jìn)程
了蕊玷,并返回相應(yīng)的 process id邮利,其具體實(shí)現(xiàn)是本地方法,這里就不再深究了垃帅。如果得到相應(yīng)的 Pid延届,接下來看看應(yīng)用進(jìn)程是如何初始化的。
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
parsedArgs.appDataDir);
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
(7) handleChildProc 方法贸诚,其中的重點(diǎn)就在 RuntimeInit.zygoteInit 方法 和 ZygoteInit.invokeStaticMain 方法方庭。一個(gè)調(diào)用初始化了相應(yīng)的進(jìn)程,另一個(gè)在調(diào)用了進(jìn)程的 main 方法酱固。
private void handleChildProc(Arguments parsedArgs,
FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
}
}
在 RuntimeInit.zygoteInit 方法里實(shí)現(xiàn)了相應(yīng)的 AndroidRuntime 初始化械念,并初始化 Binder Driver 相關(guān)的文件,同時(shí)設(shè)置了 UncaughtHandler(應(yīng)用程序崩潰)运悲。在這個(gè)方法調(diào)用結(jié)束后龄减,應(yīng)用進(jìn)程就具備與相應(yīng)系統(tǒng)服務(wù)進(jìn)行 IPC 通信的能力起宽。
(8) ZygoteInit.invokeStaticMain 通過反射調(diào)用了 ZygoteInit.MethodAndArgsCaller猴娩,而這個(gè)就是相應(yīng)的 ActivityThread.java
中的 main 方法录择,其所運(yùn)行的進(jìn)程诗箍,就是大家耳熟能祥的主線程,也成為 UI 線程脖苏。
static void invokeStaticMain(ClassLoader loader,
String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = loader.loadClass(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
到此為止程拭,整個(gè)應(yīng)用進(jìn)程啟動(dòng)完畢。
應(yīng)用進(jìn)程啟動(dòng)總結(jié)
Launcher 中的 Icon 點(diǎn)擊棍潘,broadcast 發(fā)送恃鞋,啟動(dòng) Service 等組件見的跳轉(zhuǎn),都會(huì)通過 AndroidManagerProxy
來進(jìn)行中轉(zhuǎn)亦歉,而 AndroidManagerProxy
通過向 SystemServer
請(qǐng)求名為 Activity
的 ActivityManagerService
的 Binder 對(duì)象恤浪,這個(gè) Binder 對(duì)象可以粗略地看作是 ActivityManagerService
的句柄,從 Binder 對(duì)象可實(shí)際操作 ActivityManagerService
肴楷。
ActivityManagerService
在實(shí)際啟動(dòng)相應(yīng)組件時(shí)水由,會(huì)先判斷是否有相應(yīng)的 ProcessRecord,如果不存在赛蔫,就需要新建進(jìn)程砂客,這個(gè)進(jìn)程就是相應(yīng)的應(yīng)用進(jìn)程。ActivityManagerService
通過 Socket 通信的方式和 Zygote 進(jìn)行協(xié)商呵恢,Zygote 在其監(jiān)聽的 /dev/socket/zygote
socket 中發(fā)現(xiàn)有需要?jiǎng)?chuàng)建進(jìn)程的請(qǐng)求后鞠值,會(huì) fork 自身,并返回相應(yīng)的 Process Id渗钉。這個(gè) Process 會(huì)進(jìn)行相應(yīng)的初始化彤恶,使得其具備與系統(tǒng)服務(wù)進(jìn)行 IPC 通信的能力,在此之后鳄橘,調(diào)用 ActivityThread
中的 main 方法声离,開啟 Looper,主線程啟動(dòng)瘫怜。到此為止抵恋,整個(gè)應(yīng)用進(jìn)程啟動(dòng)完畢。
參考文獻(xiàn)
- Android應(yīng)用程序進(jìn)程啟動(dòng)過程的源代碼分析
- Android應(yīng)用程序線程消息循環(huán)模型分析
- startActivity流程分析(一)
- Android四大組件 Activity啟動(dòng)過程源碼分析
- Android Application Launch
文檔信息
- 版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證)
- 發(fā)表日期: 2016年6月26日
- 社交媒體: weibo
- Feed訂閱:www.woaitqs.cc/feed.xml