ZygoteInit.main
SS003 已说明 AndroidRuntime.start() 如何把控制权交给 Java。现在进入 Java 入口 ZygoteInit.main():它不是普通的 main 函数,而是把“禁止过早建线程、预加载、初始 GC、native 状态、fork SystemServer、创建 ZygoteServer、进入命令循环”排成严格顺序。本文只负责这条启动编排;预加载子项、SystemServer 服务组和应用 fork 参数将在后续文章分别展开。
1. 入口状态
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
相关函数:main(String[] argv)
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
ZygoteHooks.startZygoteNoThreadCreation();
try {
Os.setpgid(0, 0);
final long startTime = SystemClock.elapsedRealtime();
final boolean isRuntimeRestarted = "1".equals(
SystemProperties.get("sys.boot_completed"));
String bootTimeTag = Process.is64Bit()
? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog =
new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK);
RuntimeInit.preForkInit();startZygoteNoThreadCreation() 先把 fork 前的线程创建约束设置好;setpgid(0, 0) 让 Zygote 进入自己的进程组,便于后续管理。启动计时和 RuntimeInit.preForkInit() 属于运行时准备,不是服务注册,也不是应用进程 specialization。
2. 参数解析与ABI
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
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]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}start-system-server 控制是否执行 forkSystemServer();--enable-lazy-preload 延后预加载;ABI 列表供 ZygoteServer 和后续连接选择可用指令集;socket 名称区分 primary/secondary Zygote。未知参数直接抛异常,说明这不是可忽略的业务 option,而是 Zygote 启动协议错误。
3. 预加载与初始GC
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
if (!enableLazyPreload) {
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();
}
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();
bootTimingsTraceLog.traceEnd();预加载默认发生在第一次 fork 之前,使子进程可以通过 COW 共享已加载的类、资源和运行时结构。启用 lazy preload 时,这里跳过即时加载,但代码仍在第一次 fork 前通过其他路径补齐所需资源。gcAndFinalize() 清理启动阶段临时对象;它不是“回收所有未来应用对象”,而是为 fork 建立更稳定的初始堆状态。
4. Native状态
Zygote.initNativeState(isPrimaryZygote);
ZygoteHooks.stopZygoteNoThreadCreation();
zygoteServer = new ZygoteServer(isPrimaryZygote);这三步分别完成 native Zygote 状态初始化、解除“禁止创建线程”的启动阶段限制、建立 Java ZygoteServer。顺序不能交换:服务器对象要在 native 状态准备后创建;解除限制也必须发生在 fork 前准备完成之后。
5. 父子分流
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
if (startSystemServer) {
Runnable r = forkSystemServer(
abiList, zygoteSocketName, zygoteServer);
// parent: null; child: Runnable
if (r != null) {
r.run();
return;
}
}forkSystemServer() 在子进程返回一个进入 SystemServer 的 Runnable,在父 Zygote 返回 null。子进程运行 Runnable 后直接 return,不再继续监听 Zygote socket;父进程则继续执行下面的 runSelectLoop()。这正是“SystemServer 是 Zygote fork 的子进程,而不是 ZygoteServer 的一个普通客户端”的源码证据。
6. Socket收尾
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
if (caller != null) {
caller.run();
}finally 无论异常还是 select loop 提前返回都会尝试关闭 server socket。正常父 Zygote 的 select loop 不返回;子进程在 fork 后提前返回时,closeServerSocket() 防止继承的监听 fd 留在 SystemServer。若 caller 非空,表示当前已是 fork 后的子进程,需要执行连接命令对应的 Runnable。
7. 命令循环边界
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
runSelectLoop() 构造 pollfd 数组,把主 Zygote socket、USAP 事件 fd 和已有 ZygoteConnection fd 纳入同一次 Os.poll()。poll 超时用于 USAP pool refill;fd 可读时,索引 0 接受新连接,其余 fd 交给对应连接处理。这个循环的消费者是 fork 请求和 USAP 管理,不是 SystemServer 的 Binder Looper。
8. 失败定位
# 入口参数、预加载、fork 和 finally 收尾
rg -n "startZygoteNoThreadCreation|startSystemServer|enableLazyPreload|preload\(|gcAndFinalize|forkSystemServer|runSelectLoop|closeServerSocket" \
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
# poll fd、连接接受、USAP refill 与子进程连接处理
rg -n "runSelectLoop|Os\.poll|acceptCommandPeer|fillUsapPool|closeServerSocket" \
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java常见误读是把 forkSystemServer() 的父返回值和子返回值混在一起,或者看到 closeServerSocket() 就认为 Zygote 已退出。正确判断必须结合当前进程分支:父进程关闭动作通常只发生在最终退出/异常,子进程则在进入 SystemServer 前主动关闭继承的监听 socket。
下一篇将只展开 registerServerSocketFromEnv():init 创建的 socket fd 如何通过环境变量进入 ZygoteServer,以及 fd 包装、命名和关闭 owner 如何衔接。
