Zygote进程的启动-Java篇
Zygote进程是Android中Java世界的第一个进程,同时它也是Android中所有Java进程的父进程(Android所有的Java进程都从Zygote进程fork)。前面讲完了init进程到Zygote进程,只是讲述了nitive层的init进程启动及如何拉起Zygote进程,在上篇文章中最后讲到的是,app_process.cpp的main方法通过JNI,调用com.android.internal.os.ZygoteInit.java的main方法。
ZygoteInit.java main方法。
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error. 标记zygote开始启动,不让创建线程
ZygoteHooks.startZygoteNoThreadCreation();
// Zygote goes into its own process group. zygote进入自己的进程组
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart 向tron报告Zygote启动时间,除非它是运行时重新启动
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
RuntimeInit.preForkInit();//fork 预备工作?
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true;//会走这里
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true; // 好像没有这个
} else if (argv[i].startsWith(ABI_LIST_ARG)) {//有这个
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {//没有这个
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); //true
if (abiList == null) {//不为空
throw new RuntimeException("No ABI list supplied.");
}
// In some configurations, we avoid preloading resources and classes eagerly.在某些配置中,我们避免急于预加载资源和类。
// In such cases, we will preload things prior to our first fork.在这种情况下,我们将在第一个分叉之前预装东西。
if (!enableLazyPreload) {//会走这里,好像是预加载一些东西。看下面的变量名,是跟log有关?
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
}
// Do an initial gc to clean up after startup 启动后进行初始gc清理
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();//开始之前先清理一下?
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog.traceEnd(); // ZygoteInit
/*
* 调用native方法初始化zygote,包括 获取socket ,初始化安全属性 加载新能配置文件等等
*/
Zygote.initNativeState(isPrimaryZygote);//isPrimaryZygote = true
ZygoteHooks.stopZygoteNoThreadCreation();//跟前面的startZygoteNoThreadCreation对应,到这应该zygote创建出来了,可以允许创建线程了
zygoteServer = new ZygoteServer(isPrimaryZygote);//创建一个ZygoteServer对象,isPrimaryZygote 用来区分是zygote还是zygote的子进程
if (startSystemServer) {//这里是true
//孵化出 system server进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// 这里边有意思的是 调用上面的forkSystemServer 进行孵化 system server进程的时候,fork出的进程(新进程是:system server),程序也是运行到这里,相当与复制一样。两个进程都运行着同一套代码,但是这两个进程会在forkSystemServer方法得到不同的返回值,然后下面开始分道扬镳,走各自的路。
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
/*
* 如果是父进程(即:zygote进程),r是null
* 如果是子进程(在这里就是:system server)
*/
if (r != null) {
r.run(); //所以zygote进程不会进来这里,但是system server进程会走到这里
return;
}
}
//zygote进程会走到这里
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
//zygote进程开启循环 ,等待socket连接,有请求的时候,就去fork新进程
caller = zygoteServer.runSelectLoop(abiList);//返回来的caller是子进程的Runnable,
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {//断开socket连接
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {//非System server子进程,在这里调用,子进程开始自己的任务
caller.run();
}
}
总结
在上述的main方法中,主要做的事情:
- zygote进程创建的时候,不允许创建线程
- RuntimeInit.preForkInit(); fork 预备工作
- 参数解析,判断是不是zygote模式
- 做一些清理工作
- Zygote.initNativeState(isPrimaryZygote),调用native方法,获取socket、加载配置文件等
- 开放创建线程,与1对应
- 创建一个ZygoteServer对象
- 调用forkSystemServer,孵化system server进程
- 当system server进程孵化出来之后,两个进程开始分道扬镳
- zygote进程:开启循环,等待socket客户端请求到来,孵化新进程。然后调用runSelectLoop方法返回的Runnable对象的run方法,开始子进程的任务
- system server进程:运行forkSystemServer方法返回的Runnable对象的run方法,开始自己的任务
到这,Zygote进程就启动起来了,同时它也拉起了System server进程,而自己进入了循环状态