跨进程协作过程:

详细步骤解析
第一步:发起 Fork 请求(从 System Server 到 Zygote)
- 起点: 当系统需要启动一个应用组件(如 Activity)而该应用进程不存在时,
ActivityManagerService
(AMS) 会决定要启动一个新进程 - 准备参数: AMS 会收集所有启动新进程所需的信息,例如:
○ 应用包名: 用于识别应用身份
○ 进程名: 通常是包名或带有特定后缀(如 :background
)
○ UID/GID: 应用的用户和组 ID,用于沙盒隔离
○ 目标 SDK 版本: 用于兼容性控制
○ 入口类名: 即 android.app.ActivityThread
○ 其他标志位: 用于控制运行行为(如是否为调试应用) - 跨进程通信: AMS(运行在
system_server
进程)通过 Unix Domain Socket 向 Zygote 进程发送一个 fork 新进程的请求。这是通过 ZygoteProcess
类(其内部是 ZygoteState
)建立 Socket 连接并发送参数实现的
第二步:Zygote Fork 新进程
- 接收请求: Zygote 进程通过
ZygoteServer
一直在其 Socket 上监听来自 AMS 的请求 - 解析参数: Zygote 收到请求后,会解析参数,准备好 fork 操作
- Fork 系统调用: Zygote 调用
fork()
系统调用。这是最关键的一步
○ Zygote 的优化: 得益于 Copy-on-Write (COW) 机制,Zygote 在启动时已预加载了大量的 Android 框架类和资源(如 ActivityThread
, ContextImpl
, 通用资源等)。新 fork 出的进程几乎零成本地继承了所有这些预加载的类和信息,这极大地加快了应用启动速度并节省了内存 - 子进程(新应用进程)初始化:
○ 处理 Socket: 子进程会关闭从 Zygote 继承下来的、用于监听 fork 请求的 Socket,因为它不需要这个
○ 清理状态: 清理从 Zygote 继承的、不需要的线程和内存状态 - 执行入口方法: 在子进程中,会调用
ZygoteInit.zygoteInit()
方法,该方法主要做三件事:
○ 启动 Binder 线程池: 调用 ZygoteInit.nativeZygoteInit()
-> AppRuntime.onZygoteInit()
-> ProcessState.startThreadPool()
。这启动了 Binder 机制,使得新进程具备了 IPC 能力,可以与其他系统服务(如 AMS)进行通信
○ 关闭 Log 流: 关闭从 Zygote 继承的日志流
○ 进入主入口: 最终,通过反射调用 AMS 请求中指定的入口类的 main()
方法,即 android.app.ActivityThread.main(String[] args)
第三步:ActivityThread 接管和应用初始化
- ActivityThread.main(): 这是应用进程的“主函数”和入口点
○ 主线程初始化: 它运行在应用的主线程(UI 线程)上
○ 创建 ActivityThread 实例: ActivityThread
对象被创建,它是应用进程中的核心管理器,负责调度和管理四大组件
○ 创建 Looper: 调用 Looper.prepareMainLooper()
和 Looper.loop()
,为主线程建立消息队列(MessageQueue),开始处理消息(如 UI 事件、生命周期回调等) - attach 到系统服务:
ActivityThread.main()
方法会调用 thread.attach(false)
(其中 thread
是 ActivityThread
实例)
○ 这个方法会通过 Binder 调用 IActivityManager.attachApplication()
,最终通知到 AMS,告诉它:“我这个新进程已经启动完毕,并且准备好了” - AMS 完成后续启动: AMS 收到
attachApplication()
回调后,会知道新进程已就绪。然后它会:
○ 通过 Binder IPC 回调到应用进程的 ApplicationThread
(一个实现了 IApplicationThread
接口的 Binder 对象,是 ActivityThread
的内部类)
○ 发送 BIND_APPLICATION
等消息到应用进程的消息队列 - 加载应用 APK 和创建 Application:
○ 主线程的 H
(Handler)会处理 BIND_APPLICATION
消息
○ 这会触发 ActivityThread.handleBindApplication()
方法
○ 在该方法中,会:
◎ 创建 ContextImpl
(Context 的真正实现)
◎ 使用 LoadedApk
类的信息,通过 ClassLoader
加载应用的 APK
◎ 实例化应用的 Application
对象(根据 AndroidManifest.xml 中 <application>
的 android:name
属性,默认为 android.app.Application
)
◎ 调用 Application.onCreate()
生命周期方法。这是应用开发者可以接受到的第一个自定义回调
总结与关键点
- Zygote 的作用: 预加载通用框架资源和类,通过 fork 快速创建新进程,节省内存和启动时间
- 进程分工:
○ system_server
(AMS): 决策者。决定何时、为何启动新进程,并收集启动参数
○ Zygote
: 孵化器。负责执行 fork()
,创建进程实例
○ 应用进程: 执行者。运行 ActivityThread
和应用代码 - 两次 IPC:
① AMS -> Zygote (via Socket):请求 fork
② 应用进程 -> AMS (via Binder):通知 attach,完成后续启动流程 - 主线程消息循环:
ActivityThread.main()
的核心是启动 Looper
,使得主线程成为一个事件驱动的工作模式,所有来自系统的回调(如生命周期、界面绘制)都通过消息队列来调度