這是羅昇陽《Android 系統源代碼》一書中第12章,Android 應用程序進程的啓動過程,的摘要;
當 ActivityMangerService 啓動一個應用程序組件時,如果發現這個組件所需要的進程沒有啓動,就會請求 Zygote 啓動新的進程。Zygote 通過複製自身的方式創建一個新的進程,同時也會獲取一個虛擬機實例;
應用程序進程啓動過程中,除了獲得一個虛擬機實例外,還獲得一個 Binder 線程池和一個消息循環。
一、應用程序進程創建的過程
當 ActivityManagerService 創建一個新的進程時,會調用 ActivityManagerService.startProcessLocked 方法向 Zygote 發送一個創建進程請求;
Zygote.forkAndSpecialize(...) 通過調用native 方法 nativeForkAndSpecialize(...) ,fork 一個新的進程;
ZygoteConnection.handleChildProc(...) 啓動新的進程;
二、消息循環的創建過程
一個新的應用進程創建完成之後,就會調用 RuntimeInit 類的靜態成員函數 invokeStaticMain 將 ActivityThread 類的靜態成員函數 main 設置爲新創建的應用程序進程入口。 ActivityThread 類的靜態成員函數 main 在調用的過程中,就會在當前應用程序進程中創建一個消息循環。
RuntimeInit.invokeStaticMain 方法
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);
}
Method m;
try {
// 通過反射進入獲取ActivityThread 類的 main 方法
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException("Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException("Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);
}
/*
* 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.
*/
// 拋出 caller 異常,在 ZygoteInit 的 main 方法裏捕獲
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
在 ZygoteInit.main 方法中捕獲 caller 異常
public static void main(String argv[]) {
·····
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
···
}
}
調用 MethodAndArgsCaller.run 方法
public static class MethodAndArgsCaller extends Exception implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
// 調用 ActivityThread 類的 main 方法
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
···
}
}
}
ActivityThread.main 方法裏面開啓消息循環
public static void main(String[] args) {
···
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
··
Looper.loop();
···
}
使用拋出異常的方式進入 ActivityThread 的 main 方法的原因:
ActivityMangerService 請求 Zygote 進程創建的應用程序的入口函數爲 ActivityThread 類的 main 函數。但是由於新創建的應用程序
進程一開始就需要在內部初始化運行時庫,以及啓動 Binder 線程池,因此,當 ActivityThread 類的靜態成員函數 main 被調用時,新
創建的應用程序進程實際上已經執行了相當多的代碼。爲了使得新創建的應用程序進程覺得它的入口函數就是 ActivityThread 類的 main
,系統就不可以在 ZygoteInit.invokeStaticMain 中直接調用。而是先拋出一個異常回到 ZygoteInit 類的 main 中,然後間接調用它,這樣
巧妙利用 Java 語言的異常處理機制清理它前面的調用棧。