系統(tǒng)啟動過程
啟動Zygote進(jìn)程:
啟動過程開始于Zygote進(jìn)程贡羔,當(dāng)啟動一個應(yīng)用時葵袭,Zygote進(jìn)程會被復(fù)用以創(chuàng)建新的應(yīng)用進(jìn)程涵妥。
這里是ZygoteInit.main的主要作用,它是Zygote進(jìn)程的入口:
public class ZygoteInit {
public static void main(String argv[]) {
// ... 省略的一些前期初始化代碼
// 啟動系統(tǒng)服務(wù)進(jìn)程
if (startSystemServer) {
startSystemServer(forkedProcesses);
}
// 進(jìn)入Zygote的主循環(huán)
Runnable caller;
try {
caller = zygoteServer.runSelectLoop();
} catch (Throwable ex) {
// ... 處理異常
}
// 運行子進(jìn)程初始化代碼
if (caller != null) {
caller.run();
}
}
}
1坡锡、Zygote連接處理:
Zygote進(jìn)程在初始化后會進(jìn)入一個循環(huán)蓬网,等待來自ActivityManagerService(AMS)的進(jìn)程啟動請求块请。這是在runSelectLoop中處理的。
ZygoteServer.runSelectLoop 在后臺等待連接請求:
public class ZygoteServer {
Runnable runSelectLoop() {
while (true) {
// 等待AMS連接
ZygoteConnection connection = acceptCommandPeer();
return connection.processOneCommand(); // 這里實際上是處理一個命令
}
}
}
2拳缠、處理啟動命令:
在接收到啟動請求后墩新,ZygoteConnection.processOneCommand 方法負(fù)責(zé)處理實際啟動參數(shù)。
public class ZygoteConnection {
Runnable processOneCommand() {
// 解析啟動參數(shù)
Arguments args = readArgumentList();
// 調(diào)用Zygote來fork新進(jìn)程
Zygote.forkAndSpecialize(...);
if (pid == 0) {
// 子進(jìn)程執(zhí)行到這里
return handleChildProc(args, descriptors, childPipeFd, newStderr);
} else {
// 父進(jìn)程(Zygote進(jìn)程)執(zhí)行到這里
...
}
}
}
這 就是說窟坐,handleChildProc 方法在子進(jìn)程中被調(diào)用海渊,這里新啟動的進(jìn)程會完成初始化:
3. handleChildProc
handleChildProc 負(fù)責(zé)處理子進(jìn)程的初始化。
public class ZygoteConnection {
private Runnable handleChildProc(Arguments parsedArgs) {
// 初始化子進(jìn)程
return RuntimeInit.wrapperInit(parsedArgs);
}
}
4. RuntimeInit.wrapperInit
RuntimeInit.wrapperInit 是實際啟動應(yīng)用進(jìn)程的方法哲鸳。
public class RuntimeInit {
public static Runnable wrapperInit(Arguments args) {
return applicationInit(args);
}
private static Runnable applicationInit(Arguments args) {
return invokeStaticMain(args.startClass, args.startArgs, null);
}
protected static Runnable invokeStaticMain(String className, String[] argv, ClassLoader classLoader) {
// 反射調(diào)用main方法
Class<?> cl;
try {
cl = Class.forName(className);
Method m = cl.getMethod("main", new Class[] { String[].class });
m.invoke(null, new Object[]{argv});
} catch (Exception ex) {
throw new RuntimeException(ex);
}
return null;
}
}
5. ActivityThread.main
以上步驟最終會調(diào)用到ActivityThread.main方法臣疑,這是實際應(yīng)用進(jìn)程的入口。
public class ActivityThread {
public static void main(String[] args) {
// 主線程初始化
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
Looper.loop();
}
}
總結(jié)
整個調(diào)用鏈從Zygote接收啟動參數(shù)到涉及到的主要過程如下:
ZygoteInit.main: 啟動進(jìn)程徙菠,并進(jìn)入等待循環(huán)讯沈。
ZygoteServer.runSelectLoop: 等待并處理啟動請求。
ZygoteConnection.processOneCommand: 解析并fork新的進(jìn)程婿奔。
RuntimeInit.wrapperInit: 完成子進(jìn)程進(jìn)一步初始化缺狠。
RuntimeInit.applicationInit: 通過反射調(diào)用指定類的main方法。
ActivityThread.main: 啟動應(yīng)用主線程萍摊。
接下來看看AMS是怎么傳輸Socket數(shù)據(jù)給Zygote的
在ActivityManagerService(AMS)中挤茄,有關(guān)啟動應(yīng)用進(jìn)程并通過Socket請求發(fā)送給Zygote的部分,主要是通過startProcessLocked方法來實現(xiàn)冰木。這個方法會調(diào)用Process.start方法穷劈,并通過Zygote發(fā)送啟動請求。在啟動參數(shù)中傳遞了android.app.ActivityThread踊沸。
具體的流程如下:
1. ActivityManagerService.startProcessLocked
ActivityManagerService的startProcessLocked方法負(fù)責(zé)啟動新進(jìn)程:
public class ActivityManagerService {
private boolean startProcessLocked(ProcessRecord app, ...) {
...
// 調(diào)用Process.start來啟動進(jìn)程
Process.ProcessStartResult startResult = Process.start(
"android.app.ActivityThread", // 這里指定類名
app.processName, ...);
...
}
}
2. Process.start
Process.start方法負(fù)責(zé)創(chuàng)建并啟動一個新的應(yīng)用進(jìn)程:
public class Process {
public static ProcessStartResult start(
String processClass, // 這里是傳入的 "android.app.ActivityThread"
String niceName,
...
) {
...
try {
return startViaZygote(processClass, niceName, ...);
} catch (RuntimeException e) {
...
}
}
private static ProcessStartResult startViaZygote(
String processClass,
String niceName,
...
) {
...
// 創(chuàng)建啟動參數(shù)列表
ArrayList<String> argsForZygote = new ArrayList<String>();
// 傳遞啟動組件類名
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
argsForZygote.add("-classpath");
argsForZygote.add("--nice-name=" + niceName);
argsForZygote.add(processClass); // 傳入的類名
// 調(diào)用Zygote來啟動進(jìn)程
ProcessStartResult result = ZygoteProcess.zygoteSendArgsAndGetResult(
openZygoteSocketIfNeeded(abi), argsForZygote);
...
return result;
}
}
3. ZygoteProcess.zygoteSendArgsAndGetResult
這個方法通過Socket將啟動參數(shù)發(fā)送給Zygote進(jìn)程:
public class ZygoteProcess {
public Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
// 獲取Zygote進(jìn)程的Socket連接
DataOutputStream zygoteWriter = zygoteState.mZygoteOutputWriter;
// 發(fā)送啟動參數(shù)
for (String arg : args) {
zygoteWriter.writeBytes(arg + "\n");
}
// 獲取啟動結(jié)果
ProcessStartResult result = new ProcessStartResult();
result.pid = zygoteState.mZygoteInputStream.readInt();
...
return result;
} catch (IOException ex) {
throw new ZygoteStartFailedEx(ex);
}
}
}
傳遞給Zygote的參數(shù)
從上述代碼可以看到歇终,Process.start方法最終構(gòu)建了一個參數(shù)列表argsForZygote,其中包括要啟動的類名android.app.ActivityThread逼龟,并通過ZygoteProcess.zygoteSendArgsAndGetResult發(fā)送到Zygote進(jìn)程评凝。
4. 接受請求并啟動進(jìn)程的Zygote代碼
回到之前的細(xì)節(jié):
ZygoteServer.runSelectLoop
Zygote進(jìn)程在啟動后,會進(jìn)入一個循環(huán)等待AMS的請求:
public class ZygoteServer {
Runnable runSelectLoop() {
while (true) {
ZygoteConnection connection = acceptCommandPeer();
return connection.processOneCommand();
}
}
}
ZygoteConnection.processOneCommand
在接受到啟動請求后审轮,Zygote進(jìn)程通過processOneCommand方法處理請求:
public class ZygoteConnection {
Runnable processOneCommand() {
// 讀取并解析參數(shù)
Arguments args = readArgumentList();
// Fork新的進(jìn)程
int pid = Zygote.forkAndSpecialize(args);
if (pid == 0) {
// 子進(jìn)程處理
return handleChildProc(args);
} else {
// 父進(jìn)程處理
...
}
}
}
總結(jié)
總結(jié)來說肥哎,關(guān)于傳遞類名android.app.ActivityThread的調(diào)用鏈如下:
ActivityManagerService.startProcessLocked: 調(diào)用Process.start方法,傳入類名android.app.ActivityThread疾渣。
Process.start: 調(diào)用startViaZygote篡诽,構(gòu)建參數(shù)列表并調(diào)用ZygoteProcess.zygoteSendArgsAndGetResult。
ZygoteProcess.zygoteSendArgsAndGetResult: 通過Socket將啟動參數(shù)發(fā)給Zygote進(jìn)程榴捡。
ZygoteServer.runSelectLoop: 接受并處理啟動請求琅豆。
ZygoteConnection.processOneCommand: 解析啟動參數(shù)并fork新進(jìn)程统捶。
handleChildProc: 初始化新進(jìn)程蒿讥,最終調(diào)用RuntimeInit.zygoteInit,并反射調(diào)用ActivityThread.main翰蠢。