It's our wits that make us men.

← 源码笔记
为什么使用 Zygote 进程 fork,而不是 init 进程

为什么使用 Zygote 进程 fork,而不是 init 进程

1. 概述

项目 说明
功能描述 Android 通过 Zygote 进程 fork 所有应用进程和 SystemServer,而非由 init 进程直接 fork
涉及进程 init (PID=1) → Zygote → App 进程 / SystemServer
核心类 ZygoteInitZygoteZygoteServerZygoteConnection

2. 根本原因:三大核心优势

2.1 预加载共享,节省内存和时间(最核心)

Zygote 在 fork 之前预加载了大量公共资源。

源码: ZygoteInit.java:169-221

static void preload(TimingsTraceLog bootTimingsTraceLog) {
    preloadClasses();                    // 数千个 Java 类
    cacheNonBootClasspathClassLoaders(); // 类加载器缓存
    Resources.preloadResources();        // 系统资源 (drawable/layout/string)
    nativePreloadAppProcessHALs();       // HAL 库
    maybePreloadGraphicsDriver();        // GPU 驱动
    preloadSharedLibraries();            // 共享 .so 库
    preloadTextResources();              // 文本/字体资源
    WebViewFactory.prepareWebViewInZygote(); // WebView 引擎
}

fork 使用 COW(Copy-On-Write)机制,子进程直接共享父进程的内存页:


2.2 fork 速度极快

源码: Zygote.java:395-425

static int forkAndSpecialize(int uid, int gid, int[] gids, ...) {
    ZygoteHooks.preFork();
    int pid = nativeForkAndSpecialize(uid, gid, gids, ...);
    // fork 后子进程已具备完整的 ART 虚拟机
    ZygoteHooks.postForkCommon();
    return pid;
}

fork Zygote = 直接获得一个已初始化好 ART 虚拟机 + 预加载类库的进程

而 init 是纯 C/C++ 进程,不包含 JVM:

方式 步骤 耗时
Zygote fork fork() → 特化 (uid/gid/selinux) → 运行 毫秒级
init fork(假设) fork()exec(app_process) → 启动 ART VM → 加载类库 → 加载资源 → 运行 秒级

2.3 Zygote 是 Java 世界的”模板进程”

源码: ZygoteInit.main()(行 976)

ZygoteInit.main()
  → ZygoteHooks.startZygoteNoThreadCreation()  // 禁止创建线程(保证 fork 安全)
  → preload(...)                                 // 预加载所有公共资源
  → gcAndFinalize()                              // GC 清理,减少脏页
  → ZygoteServer.runSelectLoop()                 // 等待 AMS 发来的 fork 请求

init 进程是所有进程的祖先,但它是 C 进程,职责是:

init 不具备 Java 运行环境,无法作为 Java 应用进程的模板。


3. 调用链

步骤 类.方法() 文件路径 进程/线程
1 init 解析 init.rc system/core/init/ init 进程
2 启动 app_process frameworks/base/cmds/app_process/app_main.cpp init → zygote
3 ZygoteInit.main() frameworks/base/core/java/com/android/internal/os/ZygoteInit.java:976 Zygote 主线程
4 preload() ZygoteInit.java:169 Zygote 主线程
5 ZygoteServer.runSelectLoop() ZygoteServer.java Zygote 主线程
6 AMS 发送 fork 请求 ZygoteProcess.java system_server
7 Zygote.forkAndSpecialize() Zygote.java:395 Zygote 主线程
8 nativeForkAndSpecialize() com_android_internal_os_Zygote.cpp Zygote → 子进程
9 ActivityThread.main() ActivityThread.java App 主线程

4. 时序图

sequenceDiagram
    participant init as init (PID=1)<br/>C 进程
    participant zygote as Zygote<br/>Java 进程
    participant ams as AMS<br/>(SystemServer)
    participant app as App 进程

    init->>zygote: 启动 app_process → ZygoteInit.main()

    Note over zygote: preloadClasses()<br/>preloadResources()<br/>preloadSharedLibraries()
    Note over zygote: gcAndFinalize()

    zygote->>zygote: runSelectLoop() 等待请求

    ams->>zygote: Socket 请求: fork 新进程
    zygote->>app: fork() + specialize(uid, gid, selinux)

    Note over app: 继承 Zygote 的:<br/>- ART 虚拟机<br/>- 预加载的类<br/>- 预加载的资源<br/>- 共享库

    app->>app: ActivityThread.main()

5. 核心数据结构

类名 关键字段/方法 作用
ZygoteInit preload(), main() Zygote 入口,执行预加载并启动 Socket 监听
ZygoteServer runSelectLoop() 监听来自 AMS 的 fork 请求
ZygoteConnection processCommand() 解析 fork 参数并调用 Zygote.forkAndSpecialize()
Zygote forkAndSpecialize(), forkSystemServer() 实际执行 fork + 进程特化
ZygoteHooks preFork(), postForkCommon() fork 前后的 ART 虚拟机状态管理

6. 对比总结

维度 init fork(假设方案) Zygote fork(实际方案)
语言环境 C/C++,无 JVM 已初始化的 ART 虚拟机
预加载 无,每次从零加载 数千个类 + 系统资源已就绪
内存占用 N 个进程 × 独立加载 = 巨大 N 个进程 COW 共享 = 极小
启动速度 秒级(需 exec + VM 初始化) 毫秒级(fork 即用)
fork 安全 多线程环境 fork 不安全 startZygoteNoThreadCreation() 保证单线程
职责定位 系统初始化 / 守护进程管理 Java 应用进程孵化器

7. 要点总结


8. 推荐阅读

← 返回目录