Zygote
init -> zygote进程 -> SystemServer进程 -> 各种系统服务进程 -> 应用进程
/**
* Special method to start the system server process. In addition to the
* common actions performed in forkAndSpecialize, the pid of the child
* process is recorded such that the death of the child process will cause
* zygote to exit.
*
* @param uid the UNIX uid that the new process should setuid() to after
* fork()ing and and before spawning any threads.
* @param gid the UNIX gid that the new process should setgid() to after
* fork()ing and and before spawning any threads.
* @param gids null-ok; a list of UNIX gids that the new process should
* setgroups() to after fork and before spawning any threads.
* @param runtimeFlags bit flags that enable ART features.
* @param rlimits null-ok an array of rlimit tuples, with the second
* dimension having a length of 3 and representing
* (resource, rlim_cur, rlim_max). These are set via the posix
* setrlimit(2) call.
* @param permittedCapabilities argument for setcap()
* @param effectiveCapabilities argument for setcap()
*
* @return 0 if this is the child, pid of the child
* if this is the parent, or -1 on error.
*/
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
ZygoteHooks.postForkCommon();
return pid;
}
private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
Zygote(中文常译 “受精卵”)是 Android 系统中所有 Java 进程的 “孵化器”,其核心作用是通过预加载资源和共享进程内存,大幅减少后续 App 及系统进程(如 SystemServer)的启动时间,是 Android 高效启动机制的关键组件。
Zygote 的核心定位与设计初衷
在 Android 诞生前,传统 Linux 系统中每个新进程启动时都需重新加载虚拟机、框架类库等基础资源,导致进程启动慢且内存占用高。
Zygote 的设计初衷就是解决这一问题,核心思路是:
- 提前加载:在系统启动初期,Zygote 进程一次性加载 Java 虚拟机(ART/Dalvik)、系统核心类库(如
android.os.*、java.lang.*)和系统资源(如 framework-res.apk)。 - 进程共享:通过 Linux 的
fork()机制孵化新进程,新进程会继承 Zygote 已加载的资源(共享内存页,写时复制),无需重复加载,实现 “一键孵化”。
最终效果:App 进程启动时间从秒级缩短到毫秒级,同时减少内存冗余占用。
Zygote 的启动流程(从系统开机到就绪)
Zygote 是系统启动早期由 init 进程启动的关键进程,启动流程可分为 4 个阶段:
阶段 1:由 init 进程触发启动(系统初始化阶段)
Android 系统开机后,Linux 内核首先启动 init 进程(系统第一个用户态进程),init 进程通过解析 /init.rc(初始化配置文件)触发 Zygote 启动:
解析配置:
init.rc中定义了 Zygote 的启动脚本,指定了启动程序路径和参数:# /init.rc 中 Zygote 启动配置(以 64 位系统为例) service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server class main priority -20 user root group root readproc reserved_disk socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver启动 Zygote 进程:
init进程执行/system/bin/app_process64程序(Zygote 的可执行文件),并传入启动参数(如--zygote表示以 Zygote 模式运行,--start-system-server表示启动后需孵化 SystemServer)。
阶段 2:Zygote 初始化(加载虚拟机与核心资源)
app_process64 启动后,执行 ZygoteInit.main() 方法,完成 Zygote 自身初始化:
- 启动 Java 虚拟机(ART/Dalvik):
- 调用
AndroidRuntime.startVm()初始化虚拟机,设置虚拟机参数(如堆内存大小、垃圾回收策略)。 - 注册 JNI 方法(如
java.lang.String的 native 方法),建立 Java 层与 Native 层的通信桥梁。
- 调用
- 预加载系统核心类:
- 读取
/system/etc/preloaded-classes文件(包含需预加载的类列表,如android.app.Activity、java.util.ArrayList)。 - 通过
ClassLoader批量加载这些类到虚拟机,后续孵化的进程可直接复用,无需重复加载。
- 读取
- 预加载系统资源:
- 调用
Resources.preloadResources()加载系统资源(如/system/framework/framework-res.apk中的 drawable、layout、string 等)。 - 预加载主题资源(如默认 App 主题),避免后续 App 启动时加载资源耗时。
- 调用
- 初始化 Binder 通信通道:
- 创建
ZygoteSocket(UNIX 域套接字),用于接收其他进程(如 SystemServer、AMS)的进程孵化请求。 - 将
ZygoteSocket注册到系统,监听端口(通过runSelectLoop()进入循环监听状态)。
- 创建
阶段 3:孵化 SystemServer 进程(系统核心服务容器)
Zygote 初始化完成后,首先孵化 SystemServer 进程(系统所有核心服务的运行容器),这是 Zygote 启动后的第一个任务:
- 构造 SystemServer 启动参数:
- 配置高权限参数:
--setuid=1000(SystemServer 的 UID 为系统用户,拥有最高权限)、--setgid=1000、--nice-name=system_server(进程名)。 - 指定主类路径:
com.android.server.SystemServer(SystemServer 的入口类)。
- 配置高权限参数:
- 执行 fork () 系统调用:
- 调用
Zygote.forkSystemServer()方法,通过 Linux 的fork()机制创建子进程(SystemServer)。 - 父进程(Zygote):fork 成功后返回子进程 PID,继续监听
ZygoteSocket,准备孵化后续 App 进程。 - 子进程(SystemServer):fork 成功后返回 0,执行
handleSystemServerProcess()方法,进入 SystemServer 自身初始化流程(如启动 AMS、WMS 等服务)。
- 调用
阶段 4:进入循环监听(等待孵化 App 进程)
孵化 SystemServer 后,Zygote 调用 runSelectLoop() 进入 永久循环监听状态,等待 AMS 发送的 App 进程孵化请求:
监听 ZygoteSocket:通过 IO 多路复用(
select()系统调用)监听ZygoteSocket上的请求,避免阻塞。处理孵化请求
:当 AMS 需要启动新 App 时(如用户点击图标),会通过 Binder 发送请求到 Zygote:
- Zygote 接收请求(包含 App 的 UID、GID、包名、主类路径等参数)。
- 调用
Zygote.forkAndSpecialize()孵化新 App 进程(与 fork SystemServer 类似,但权限更低)。 - 新 App 进程初始化后,执行
ActivityThread.main()方法,启动 App 主线程。
持续服务:Zygote 会一直运行到系统关机,为所有 App 进程提供孵化服务。
Zygote 的核心特性(为什么能高效孵化进程)
- 写时复制(Copy-On-Write,COW):
- Zygote 孵化新进程时,通过 Linux 的 COW 机制共享内存页:新进程初始时不复制 Zygote 的内存,仅当新进程修改内存数据(如修改某个类的静态变量)时,才复制对应的内存页。
- 大幅减少内存占用(如多个 App 共享 Zygote 预加载的类和资源,无需各存一份)。
- 预加载机制:
- 提前加载系统类和资源,避免后续进程重复加载,缩短启动时间(App 进程启动时无需加载
android.app.Activity等基础类)。
- 提前加载系统类和资源,避免后续进程重复加载,缩短启动时间(App 进程启动时无需加载
- 单一父进程:
- 所有 Java 进程(包括 SystemServer 和 App)都由 Zygote 孵化,形成 “Zygote → 子进程” 的树形结构,便于系统统一管理(如进程优先级调整、内存回收)。
- 权限隔离:
- 孵化不同进程时配置不同的 UID/GID(如 App 进程的 UID 从 10000 开始,SystemServer 的 UID 为 1000),实现进程间权限隔离,保障系统安全。
Zygote 与其他核心组件的关系
| 组件 | 与 Zygote 的交互方式 |
|---|---|
| init 进程 | Zygote 的父进程,通过 /init.rc 启动 Zygote,Zygote 崩溃时 init 会重启 Zygote。 |
| SystemServer | Zygote 的第一个子进程,由 Zygote 孵化后启动系统核心服务;SystemServer 中的 AMS 会向 Zygote 发送 App 孵化请求。 |
| AMS | 通过 ZygoteSocket 向 Zygote 发送 App 进程孵化请求(如 startActivity() 时启动目标 App 进程);Zygote 孵化完成后,AMS 管理 App 进程的生命周期。 |
| App 进程 | 所有 App 进程都是 Zygote 的子进程,继承 Zygote 预加载的类和资源;App 进程崩溃时,由 AMS 通知 Zygote 重新孵化(可选)。 |
总结
Zygote 是 Android 系统的 “进程孵化器”,通过 预加载资源、写时复制、统一孵化 三大核心机制,实现了进程的高效启动和内存的优化利用。其启动流程贯穿系统初始化阶段,从 init 进程触发到孵化 SystemServer,再到持续监听 App 孵化请求,是连接底层 Linux 内核与上层 Java 组件的关键桥梁。理解 Zygote 的工作原理,是掌握 Android 进程管理和启动优化的核心基础。