外观
Zygote 是什么?为什么启动应用要经过它?
标准回答
Zygote 是 Android 用来孵化应用进程的重要进程。它提前准备运行时和常用类、资源等公共环境,需要新应用进程时,在这套基础上创建子进程,并为目标应用设置相应身份和运行条件。这样可以减少每个应用都从零准备公共环境的成本。
普通应用需要新进程时,系统的进程管理链路向适当的 Zygote 发出请求,典型控制通信使用 Unix domain socket。创建出的进程进入应用运行入口,完成与系统连接、应用绑定等准备,再执行组件生命周期。现代设备还可能采用 USAP 等预先创建进程的优化,所以不应把某一个版本的函数顺序当作唯一实现。
进程创建使用 fork 等机制,公共内存页可以利用写时复制共享:不修改时可以共享底层页面,发生写入后再分离。它不是把某个已经运行的业务应用完整复制一份,也不意味着不同应用可以直接修改彼此的 Java 对象。
已有可用进程时,打开新 Activity 通常不需要再次创建进程。因此启动一个页面、创建一个任务和创建一个进程是不同层次;排查冷启动慢,才需要把进程创建、应用初始化和页面首帧分别计时。
关键机制
- Zygote 准备公共基础并参与应用进程创建,不直接管理按钮布局。
- 进程出来后,还要完成绑定、应用初始化和目标组件启动。
- 热启动或已有进程的页面跳转,不必重复完整的进程创建过程。
通俗例子
第一次打开应用时要创建进程并初始化 Application;之后从首页打开详情页,若二者在同一存活进程,通常只需要页面启动链路,不能把详情页耗时都算作 Zygote 创建耗时。
追问与回答
fork 不是复制进程吗,为什么不会把内存立刻翻倍?
fork 后父子进程有独立的地址空间,但很多内存页可先共享底层物理页面。某一方需要修改时,再通过写时复制分离对应页面,所以不是立即复制所有物理内存。不过后续写入和应用自身分配仍会增加实际内存,不能理解成创建新进程没有成本。
进程有了,Application.onCreate 就一定已经结束了吗?
不是。看到 PID 只表示进程存在,后面还要进入运行入口、与系统连接、绑定应用并执行初始化。Application.onCreate 结束后,目标页面的创建和首帧也可能还没完成。测启动时应按阶段记录,不能把 PID 出现当成应用可交互。
易混淆点
Zygote 不是所有原生系统守护进程的父进程;不少原生服务由 init 启动。创建进程的 Zygote 控制请求也不是所有步骤都走 Binder。
参考资料
内容来源
- Android 技术札记 · 原条目
framework-zygote