乐于分享
好东西不私藏

App 进程是怎么被创建的

App 进程是怎么被创建的

App 进程的创建是ATMS 决策任务栈PMS 确定身份权限AMS 调度资源,最后由Zygote 物理执行 fork的接力过程。


1. 意图解析与安全准入(PMS 的静态约束)

一切始于Launcher进程调用startActivity。此时,请求进入了系统的“大脑”ATMS。

PMS 的情报作用:ATMS第一时间访问PMS。PMS解析 APK 的AndroidManifest.xml,确定目标 Activity 的UIDprocessNametaskAffinity

鉴权(Security Check):ATMS根据PMS返回的数据进行“政审”:该组件是否对外开放(exported)?调用者是否有权限?如果校验不通过,启动直接终止,保护系统安全。

2. 任务栈与进程决策(ATMS 的逻辑调度)

在确定“可以启动”后,系统要决定“在哪启动”。

TaskAffinity 判定:ATMS检查Intent的 Flag。如果包含NEW_TASK,它会根据taskAffinity字符串寻找匹配的任务栈。如果没有匹配项,就创建一个新的TaskRecord(这就是多任务界面里看到的一个新卡片)。

进程状态检查:ATMS转向AMS询问:“这个processName对应的进程活着吗?”。如果不存在,则进入冷启动流程,准备创建物理进程。

3. 物理进程孵化(Zygote 的克隆机制)

这是 Framework 向 Linux 内核层的跨越。

Socket 指令AMS构造启动参数(UID、入口类ActivityThread等),通过LocalSocket发给Zygote进程。
Fork 裂变Zygote接收指令后执行fork()。核心原理:利用 Linux 的Copy-on-Write (COW)机制,新 App 进程直接继承了Zygote预加载的所有 Framework 类和资源,实现了毫秒级启动。

4. 身份绑定与环境初始化(ActivityThread 的觉醒)

新进程诞生后,它还是一个“空壳”,需要与系统建立联系。

反射入口:进程从ActivityThread.main()开始运行,创建主线程Looper。

反向报到(Attach):新进程通过 Binder 调用AMS.attachApplication()。这步至关重要,它把自己的 Binder 代理交给系统,从此AMS才能操控这个进程。

Application 初始化:AMS回调进程执行bindApplication,触发Application.onCreate()。此时,App 的全局运行环境正式建立。

5. 生命周期分发与落地(关键生命周期的执行)

万事俱备,ATMS开始下发真正的业务指令。

事务调度:ATMS发送LaunchActivityItem事务给进程。

三部曲执行

onCreate():反射创建 Activity 实例,执行setContentView填充 View 树。
onStart():Activity 变为可见状态。
onResume():Activity 获取焦点。

6.app启动常见问题

Q1:为什么第一步必须找 PMS?

因为 Android 是基于UID (User ID)的安全沙箱。ATMS 必须通过 PMS 拿到目标 App 的 UID。如果 UID 校验不通过(比如两个 App 签名不一致且尝试共享数据),流程会在第 4 步之前被掐断。

Q2:TaskAffinity 是如何影响物理进程的?

逻辑层面:ATMS里的ActivityStarter会根据taskAffinity决定 Activity 属于哪个“卡片”(TaskRecord)。

物理层面:如果taskAffinity指向了一个新的进程名(process属性),AMS就会发现当前没有对应的ProcessRecord,从而强行触发Zygote 的 Socket 通信

Q3:为什么 Zygote 孵化时一定要用 Socket?(再次强调)

Binder = 多线程:一旦开启 Binder,进程内就有多个线程。

fork = 单线程克隆:fork出来的子进程只有发起者那一个线程,其他线程持有的锁(如堆内存锁)在子进程里永远不会释放。

结论:Zygote 必须保持单线程+Socket,确保孵化出的 App 环境是“绝对纯净”的。

Q4:App 进程是什么时候拥有 Binder 能力的?

在ActivityThread.main()之后。

进程诞生之初(Zygote fork 出的一瞬间)是没有 Binder 线程池的。

在执行attachApplication之前,程序会初始化ProcessState,此时才会开启那15 个 Binder 线程

只有开启了线程池,App 才能接收到system_server发来的scheduleTransaction指令。