zygoteInit与RuntimeInit
SS014 已说明 fork 后的 SystemServer 子进程如何设置 umask、classpath 和 profile。本篇继续追踪它怎样从 ZygoteInit.zygoteInit() 进入 RuntimeInit:先建立所有 Java 线程共用的异常/日志/网络初始化,再启动 native Binder 状态,设置 target SDK 与兼容性变化,最后用反射找到目标类的 public static main(String[])。这条链的关键是 MethodAndArgsCaller:它把反射调用包装成 Runnable,让 Zygote 在清掉启动栈后再执行 SystemServer.main。
1. zygoteInit主线
源码文件:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static Runnable zygoteInit(
int targetSdkVersion,
long[] disabledCompatChanges,
long[] enabledCompatChanges,
String[] argv,
ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG,
"RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(
Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
return RuntimeInit.applicationInit(
targetSdkVersion, disabledCompatChanges,
enabledCompatChanges, argv, classLoader);
}顺序有明确依赖:日志重定向和 commonInit 先于服务代码;nativeZygoteInit() 建立 Binder 线程池/进程状态;applicationInit() 最后才解析目标 main。返回值是 Runnable 而不是立即执行,调用者是 ZygoteInit.main() 的子进程分支。
2. commonInit状态
源码文件:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static final void commonInit() {
LoggingHandler loggingHandler = new LoggingHandler();
RuntimeHooks.setUncaughtExceptionPreHandler(loggingHandler);
Thread.setDefaultUncaughtExceptionHandler(
new KillApplicationHandler(loggingHandler));
RuntimeHooks.setTimeZoneIdSupplier(
() -> SystemProperties.get("persist.sys.timezone"));
LogManager.getLogManager().reset();
new AndroidConfig();
String userAgent = getDefaultUserAgent();
System.setProperty("http.agent", userAgent);
TrafficStats.attachSocketTagger();
initialized = true;
}commonInit() 的 owner 是 RuntimeInit 类级状态,影响 VM 中所有 Java 线程:未捕获异常先经过 LoggingHandler,再由 KillApplicationHandler 报告并终止;时区、java.util.logging、HTTP User-Agent 和 socket traffic tagger 也在这里统一接入 Android 实现。initialized 只表示这段公共初始化已运行,不代表 SystemServer 服务已经启动。
3. 日志和异常处理
private static class LoggingHandler
implements Thread.UncaughtExceptionHandler {
public volatile boolean mTriggered = false;
@Override
public void uncaughtException(Thread t, Throwable e) {
mTriggered = true;
if (mCrashing) return;
if (mApplicationObject == null
&& Process.SYSTEM_UID == Process.myUid()) {
Clog_e(TAG,
"*** FATAL EXCEPTION IN SYSTEM PROCESS: "
+ t.getName(), e);
mCrashCount = SystemProperties.getInt(
SYSPROP_CRASH_COUNT, 0) + 1;
SystemProperties.set(
SYSPROP_CRASH_COUNT, String.valueOf(mCrashCount));
} else {
logUncaught(t.getName(),
ActivityThread.currentProcessName(),
Process.myPid(), e);
}
}
}SystemServer 以 system UID 且尚未设置 application object 时走 system process 日志分支,并递增 crash count;普通应用或工具走带进程名/PID 的 FATAL EXCEPTION。KillApplicationHandler 随后尝试停止 profiling、通过 ActivityManager 报告 crash,最终 killProcess 和 System.exit(10);报告服务已死亡时只记录原始异常,避免二次错误覆盖根因。
4. 参数与兼容性
源码文件:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(
int targetSdkVersion,
long[] disabledCompatChanges,
long[] enabledCompatChanges,
String[] argv,
ClassLoader classLoader) {
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
VMRuntime.getRuntime().setDisabledCompatChanges(
disabledCompatChanges);
if (disabledCompatChanges != null
|| enabledCompatChanges != null) {
AppCompatCallbacks.install(
disabledCompatChanges, enabledCompatChanges,
null, false, targetSdkVersion);
}
Arguments args = new Arguments(argv);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return findStaticMain(
args.startClass, args.startArgs, classLoader);
}nativeSetExitWithoutCleanup(true) 防止应用调用 System.exit() 时执行会关闭 Binder driver 的通用 shutdown hooks;Android 进程由 kill/退出路径管理。target SDK 和 compat changes 在加载目标类前写入 ART,保证静态初始化也看到正确兼容规则。Arguments 把 argv 拆成 start class 与剩余参数,随后关闭 zygoteInit 的 trace section 并进入反射查找。
5. 静态main查找
protected static Runnable findStaticMain(
String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main "
+ className, ex);
}
Method m;
try {
m = cl.getMethod("main",
new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing 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);
}
return new MethodAndArgsCaller(m, argv);
}类加载使用传入 classloader;SystemServer 使用 SS014 创建的 shared namespace classloader,child zygote 则可能传 null。方法签名必须精确是 main(String[]) 且同时 public/static,否则在执行目标代码前失败。返回 MethodAndArgsCaller 而不是直接 m.invoke,是为了把反射启动栈移出后续业务调用。
6. Runnable执行
static class MethodAndArgsCaller implements Runnable {
private final Method mMethod;
private final String[] mArgs;
@Override
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}mMethod.invoke 的 target 是 null,因为 main 是 static;参数包装为单个 String[]。InvocationTargetException 被拆出原始 RuntimeException/Error,保证 SystemServer.main 的失败类型和堆栈更接近真实业务异常。ZygoteInit.main() 调用 caller.run() 后,若 main 正常返回,Zygote 子进程主线也随之结束或进入后续循环约束。
7. 失败定位
commonInit()前失败:查日志流、异常 handler、时区/HTTP/TrafficStats 初始化;nativeZygoteInit()失败:查 Binder 进程状态和线程池,而不是 Java main 反射;applicationInit()参数错误:查 target SDK、compat changes 和Arguments;findStaticMain()失败:查 classloader、类名、main 签名和 public/static 修饰符;MethodAndArgsCaller.run()失败:查 SystemServer.main 原始异常及 crash handler。
# zygoteInit 交接和 native Binder 初始化
rg -n "zygoteInit|redirectLogStreams|commonInit|nativeZygoteInit|applicationInit" \
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
# RuntimeInit 全局初始化、兼容参数和静态 main 反射
rg -n "commonInit|applicationInit|findStaticMain|MethodAndArgsCaller|nativeSetExitWithoutCleanup" \
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java下一篇将进入 SystemServer.main() 与 SystemServer.run(),展开主 Looper、SystemContext 和服务启动分组;不会重复本文的 RuntimeInit 和反射调用。
