Skip to content

zygoteInit与RuntimeInit

追踪 zygoteInit、RuntimeInit.commonInit、applicationInit、findStaticMain 与 MethodAndArgsCaller 的完整交接。

基于android-17.0.0_r1
AndroidSystemServerRuntimeInit源码阅读

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

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

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. 日志和异常处理 ​

java
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

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查找 ​

java
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执行 ​

java
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。
bash
# 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 和反射调用。