核心思想:孵化器模式
你可以把Zygote进程想象成一个 "受精卵"。它的核心思想是:
- 预加载:在系统启动时,Zygote进程就预先加载了Android应用框架所需的大部分类和资源。这包括通用的SDK类、主题资源、系统共享库等
- Fork:当需要启动一个新App时,系统不是从零开始创建一个新进程并重新加载所有东西,而是直接"复制"Zygote这个已经准备好的进程
- 效率 :Fork是一个在Unix/Linux系统中非常快速的系统调用,它通过写时拷贝技术来高效地复制进程。因为大部分内存空间在初始阶段都是只读共享的,所以这个方法极大地缩短了应用启动时间 并节约了内存
详细流程分解
整个过程涉及多个系统组件,下图清晰地展示了它们之间的交互时序:

下面我们来详细解读图中的每一步:
第一步:触发启动
用户在Launcher上点击一个App图标,或者从一个App内部启动另一个Activity。这个请求最终会通过Binder IPC传递给系统核心服务 ActivityManagerService
第二步:AMS决策
AMS收到启动请求后,会解析Intent,找到要启动的Activity组件。然后,它会检查这个组件所属的应用程序进程是否已经存在
- 如果进程已存在:AMS会直接通知该进程创建并运行新的Activity
- 如果进程不存在(这是我们讨论的情况):AMS需要先为这个App创建一个新进程
第三步:准备Fork参数
AMS通过一个名为 ZygoteProcess 的类与Zygote进程通信。它会组装Fork新进程所需的所有参数,例如:
--runtime-init:指示新进程需要初始化Android运行时--target-sdk-version:目标SDK版本--nice-name:进程的友好名称(如com.example.myapp)- 应用的主类名,通常是
android.app.ActivityThread
第四步:通过Socket发起Fork请求
- 通信机制 :AMS(作为客户端)通过一个Unix域套接字与Zygote进程(作为服务端)通信。Zygote在启动后就会在一个名为
zygote的Socket上循环监听请求 - 发送请求 :
ZygoteProcess连接到Zygote Socket,将组装好的参数写入Socket - Zygote处理 :Zygote进程的
ZygoteServer监听到新的连接请求,读取参数
第五步:Fork出新进程
这是最关键的一步。Zygote进程调用 fork() 系统调用
fork()会创建一个与Zygote进程几乎完全一样的子进程- 这个子进程继承了Zygote的预加载类 、资源 和已打开的库
- 此时,子进程和Zygote共享大部分物理内存页(得益于写时拷贝技术)
第六步:子进程的初始化(化身成App)
Fork出来的子进程虽然复制了Zygote,但它还不是一个真正的App进程。它需要"改头换面"。在子进程中,会执行 ZygoteInit.zygoteInit() 方法:
- 关闭Zygote Socket:子进程不需要监听Fork请求,所以会关闭从父进程继承过来的Socket
- 初始化Binder线程池 :创建
Binder线程,使新进程能够参与系统级的Binder IPC通信。这样AMS才能与它交互 - 反射调用ActivityThread.main() :这是Android App的入口点!程序执行流程从此离开Zygote的框架代码,进入App的代码空间
○ActivityThread.main()会初始化主线程Looper
○ 创建一个Application对象
○ 调用Application.onCreate()生命周期方法
○ 最后,新进程会通过Binder告诉AMS:"我准备好了"
第七步:AMS完成启动
AMS收到新进程"已就绪"的消息后,会通过Binder IPC向新进程发送信息,告诉它:"现在可以启动那个最初请求的Activity了"。新进程随后创建并执行目标Activity,用户就看到App界面了
总结与关键点
- 核心机制 :Fork + 写时拷贝。这是高效创建App进程的基石
- 准备工作 :Zygote在系统启动时预加载通用代码和资源,避免了每个App都重复加载
- 通信方式 :AMS通过 Unix Domain Socket 向Zygote发起Fork请求
- 进程的"灵魂" :Fork出的子进程通过执行
ActivityThread.main(),从一个空的Zygote副本"变身"为真正的App进程 - 安全性:Zygote本身以root权限运行,但Fork出的子进程会根据App的配置(在AndroidManifest.xml中)被降权,以非root的沙箱权限运行,保证了系统安全