Android 应用进程启动

发布于:2025-09-06 ⋅ 阅读:(14) ⋅ 点赞:(0)

跨进程协作过程:

详细步骤解析

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

网站公告

今日签到

点亮在社区的每一天
去签到