App启动流程
核心概念前置
在讲解流程前,先明确两个关键概念:
核心进程角色:
- Launcher 进程:桌面应用进程,负责展示 App 图标、接收点击事件;
- SystemServer 进程:系统核心进程(zygote 孵化),包含 ActivityManagerService(AMS)、PackageManagerService(PMS)等核心服务;
- Zygote 进程:Android 系统的 “进程孵化器”,负责孵化新的 App 进程;
- App 进程:冷启动时新建的目标 App 进程,承载 App 的所有业务逻辑。
核心 IPC 方式:
Android 中进程间通信的核心是Binder(基于 C/S 架构的跨进程通信机制),以下流程中所有 IPC 均基于 Binder 实现。
Android 系统启动流程思维导图

App 冷启动完整流程(点击 Launcher 图标开始)
- Android App 冷启动的核心链路是:
Launcher → AMS → Zygote → App进程 → AMS → App进程,其中除 AMS 向 Zygote 的调用用 Socket,其余均为 Binder IPC; - Binder 是 Android 跨进程通信的核心,支撑了系统服务与应用进程、应用进程之间的交互;
- 冷启动的性能瓶颈主要在 Zygote 孵化进程、App 初始化、首屏绘制三个阶段,也是日常优化的重点。
阶段 1:Launcher 进程处理点击事件,向 AMS 发起启动请求
- 用户点击 App 图标:Launcher 的
onClick()事件触发,封装启动参数(包名、启动 Activity 等); - Launcher 进程 → SystemServer 进程(AMS):
- IPC 调用:Launcher 通过
ActivityManager.getService()获取 AMS 的 Binder 代理对象,调用AMS.startActivity()方法; - 核心数据:传递
Intent(包含目标 App 包名、启动模式等)、用户 ID、启动标志(如 FLAG_ACTIVITY_NEW_TASK)。
- IPC 调用:Launcher 通过
阶段 2:SystemServer 进程(AMS)校验并准备启动 App
- AMS 权限 / 参数校验:
- 调用 PMS(PackageManagerService)校验目标 App 是否安装、是否有启动权限;
- 解析 App 的 AndroidManifest.xml,获取默认启动
Activity(<intent-filter>中 ACTION_MAIN+CATEGORY_LAUNCHER);
- AMS 判断进程状态:
- 冷启动场景下,判定目标 App 无进程,触发 “新建进程 + 启动 Activity” 流程;
- 记录 Activity 启动栈,维护任务栈(TaskStack)信息。
阶段 3:SystemServer 进程(AMS)向 Zygote 进程请求孵化 App 进程
- AMS → Zygote 进程:
- IPC 调用:AMS 通过
ZygoteProcess向 Zygote 进程发送孵化请求(基于 Socket 通信,Binder 不支持跨 UID 的 Zygote 进程调用); - 核心数据:传递 App 的 UID/GID、进程名、虚拟机参数(如堆大小)、启动类(ActivityThread)。
- IPC 调用:AMS 通过
- Zygote 孵化 App 进程:
- Zygote 通过
fork()系统调用创建新进程(继承 Zygote 的虚拟机、类加载器等,避免重复初始化); - 新进程执行
ActivityThread.main()方法,启动 App 的主线程 Looper,完成进程初始化。
- Zygote 通过
阶段 4:App 进程初始化,向 AMS 注册并请求启动 Activity
- App 进程初始化:
- 启动 ActivityThread(App 进程的核心主线程类),创建 ApplicationThread(Binder 线程,负责与 AMS 跨进程通信)和 H(Handler,负责线程切换,将 Binder 线程的消息转发到主线程)。;
- 初始化主线程 Looper、Handler,创建
Application对象,执行Application.attachBaseContext()、onCreate();
- App 进程 → SystemServer 进程(AMS):
- IPC 调用:App 进程通过
ApplicationThread向 AMS 发送attachApplication()请求,注册自身进程信息; - 核心数据:传递 App 进程的 PID、ApplicationThread 的 Binder 代理对象。
- IPC 调用:App 进程通过
ApplicationThread是ActivityThread的内部类,作为ATMS回调应用进程的Binder接口:
final ApplicationThread mAppThread = new ApplicationThread();
// ActivityThread内部类
private class ApplicationThread extends IApplicationThread.Stub {
public final void bindApplication(...) {
sendMessage(H.BIND_APPLICATION, data);
}
public final void scheduleLaunchActivity(...) {
sendMessage(H.LAUNCH_ACTIVITY, r);
}
}
应用进程使用H(Handler)处理消息:
class H extends Handler {
public void handleMessage(Message msg) {
case BIND_APPLICATION:
handleBindApplication(data);
case LAUNCH_ACTIVITY:
handleLaunchActivity(r);
}
}
阶段 5:AMS 向 App 进程下发启动 Activity 指令
- AMS 确认注册:AMS 收到 App 进程的注册请求后,确认进程已就绪;
- SystemServer 进程(AMS) → App 进程:
- IPC 调用:AMS 通过 App 进程注册的
ApplicationThread代理对象,调用scheduleLaunchActivity()方法; - 核心数据:传递启动 Activity 的组件信息、Intent、任务栈信息、窗口配置(如屏幕尺寸)。
- IPC 调用:AMS 通过 App 进程注册的
阶段 6:App 进程启动 Activity,绘制界面
- App 进程处理启动指令:
ApplicationThread接收到指令后,通过主线程 Handler 将请求转发给 ActivityThread;- ActivityThread 执行
performLaunchActivity():创建 Activity 对象、执行onCreate()/onStart()/onResume();- 创建 Application 实例:调用
attachBaseContext()→ 调用onCreate()(开发者在此初始化全局资源)。 - 创建主 Activity 实例:执行
onCreate()→onStart()→onResume()生命周期方法。 - 执行 View 渲染流程:
measure→layout→draw,最终通过 SurfaceFlinger 合成显示到屏幕。
- 创建 Application 实例:调用
创建Application
handleBindApplication() 触发应用级初始化:
// frameworks/base/core/java/android/app/ActivityThread.java
private void handleBindApplication(AppBindData data) {
// 1. 创建LoadedApk(代表加载的APK)
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
// 2. 创建ContextImpl
final ContextImpl appContext = ContextImpl.createAppContext(this, pi);
// 3. 实例化Application
Application app = pi.makeApplication(forceDefaultAppClass, instr);
// 4. 安装ContentProviders
if (!data.restrictedBackupMode) {
installContentProviders(app, data.providers);
}
// 5. 回调Application.onCreate()
mInstrumentation.callApplicationOnCreate(app);
}
关键步骤:
- 通过
ClassLoader加载APK资源 - 创建应用级上下文
- 反射实例化自定义Application类
- 触发应用初始化回调
Application.attachBaseContext()何时调用?
在创建Application实例后立即调用:
// frameworks/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
// 1. 创建Application实例
Application app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
return app;
}
// frameworks/base/core/java/android/app/Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context) {
Application app = getFactory(context).instantiateApplication(cl, className);
// 关键调用
app.attach(context);
return app;
}
// frameworks/base/core/java/android/app/Application.java
final void attach(Context context) {
attachBaseContext(context); // 调用Application的protected方法
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
Activity实例化与生命周期
收到LAUNCH_ACTIVITY消息后,创建目标Activity:
// frameworks/base/core/java/android/app/ActivityThread.java
private Activity handleLaunchActivity(ActivityClientRecord r) {
final Activity a = performLaunchActivity(r, null);
return a;
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 1. 创建Activity实例
Activity activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
// 2. 创建Application(如果尚未创建)
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 3. 关联Context
Context appContext = createBaseContextForActivity(r, activity);
activity.attach(appContext, ...);
// 4. 回调onCreate()
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
return activity;
}
- 界面绘制与显示:
- Activity 执行
setContentView(),加载布局并通过 WindowManagerService(WMS)完成界面绘制; - WMS 将绘制好的 Surface 渲染到屏幕,用户看到 App 界面,冷启动完成。
- Activity 执行
全流程关键节点时序图

关键步骤拆解(新手能懂的细节)
1. 前置:指令如何从AMS到App进程?
- AMS(ActivityManagerService)运行在
system_server系统进程,App进程是独立的应用进程; - 两者通过Binder跨进程通信传递启动指令:AMS → Binder驱动 → App进程的
ApplicationThread(ActivityThread的内部类,负责跨进程通信)。
2. ApplicationThread → Handler 转发的核心原因
ApplicationThread的回调方法运行在Binder线程池(非主线程);- Android规定:Activity/Application的生命周期方法必须在主线程执行;
- 所以
ApplicationThread会通过ActivityThread的主线程Handler(mH),将启动请求封装成Message,发送到主线程的MessageQueue; - 主线程Looper取出Message后,触发
performLaunchActivity(),保证生命周期在主线程执行。
3. performLaunchActivity() 的核心工作(源码简化逻辑)
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 1. 创建Application实例(若未创建)
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
// 2. 创建Activity实例(通过类加载器反射)
Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
// 3. 关联Application上下文
activity.attach(appContext, this, ...);
// 4. 触发Activity生命周期
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
mInstrumentation.callActivityOnStart(activity);
mInstrumentation.callActivityOnResume(activity);
return activity;
}
✅ 关键:Application只在首次启动时创建,后续启动新Activity不会重复创建Application。
4. Application 生命周期(比你写的更完整)
attachBaseContext() → onCreate() → onConfigurationChanged()(配置变化)→ onLowMemory()(低内存)→ onTerminate()(仅模拟环境生效)
attachBaseContext():最早执行,此时Context已初始化,可做上下文相关初始化(如多语言、插件化);onCreate():开发者主要的初始化入口(如路由、网络、缓存初始化)。
5. View渲染流程与Activity生命周期的联动
onCreate()中调用setContentView():只是加载布局文件到内存,未执行measure/layout/draw;- 真正的View渲染触发时机:
onResume()执行后,ActivityThread通过WindowManager向WMS申请Surface,触发measure → layout → draw; - 渲染完成后,数据通过SurfaceFlinger(系统服务)合成最终帧,显示到屏幕。
易踩坑的关键细节(实战/面试高频)
onResume() ≠ 界面可见:
onResume()只是Activity进入前台的生命周期标记,此时View可能还在渲染中,真正可见要等onWindowFocusChanged(true);- 若在
onResume()中获取View宽高,会得到0(因为measure还没执行),需用View.post()或OnGlobalLayoutListener。
Application.onCreate() 不能做耗时操作:
- 它运行在主线程,耗时操作(如网络请求、复杂计算)会阻塞Activity启动,导致冷启动耗时过长。
Handler转发的线程安全:
ApplicationThread的Binder线程池是多线程的,通过主线程Handler转发,保证了生命周期方法的线程安全。
核心流程关键点
- 启动指令通过Binder跨进程从AMS到App进程,再通过Handler转发到主线程;
- Application仅首次启动创建,生命周期:
attachBaseContext() → onCreate(); - Activity创建后依次执行
onCreate() → onStart() → onResume(),随后触发View渲染; - 最终通过SurfaceFlinger完成屏幕显示。
实战优化核心
- 减少Application.onCreate()的耗时操作(如懒加载);
- 延迟非首屏必要的View渲染(如列表预加载);
- 利用
attachBaseContext()做早期上下文初始化。
简单记:Binder传指令,Handler调主线,App只创一次,渲染在Resume后。
Binder线程池是什么?
Binder机制 |
1. Binder的核心角色(跨进程通信基础)
Android的跨进程通信(IPC)核心是Binder,任何两个进程通信都要遵循“客户端-服务端”模型:
- 客户端:发起请求的一方(比如system_server进程的AMS,向App进程发启动Activity指令);
- 服务端:处理请求的一方(比如App进程的ApplicationThread,接收AMS的指令);
- Binder驱动:中间层,负责转发请求和响应,类似“快递员”。
2. Binder线程池的本质
- 每个App进程启动时,系统会自动为其创建一个Binder线程池(属于App进程的子线程池);
- 这个线程池的作用:专门处理“其他进程通过Binder发给当前App的请求”;
- 线程池的特性:多线程、自动管理、可扩容——默认创建2-4个线程,若请求多,系统会自动增加线程数(上限一般16个)。
3. 通俗例子
把App进程比作“公司”,Binder线程池是“公司的客服部门”:
- 客服部门有多个客服人员(多线程),而非只有1个;
- 外部公司(比如system_server)打来的电话(Binder请求),会被随机分配给任意一个客服人员处理;
- 即使一个客服在处理“启动Activity”的电话,另一个客服还能处理“暂停Activity”的电话,不会互相阻塞。
为什么ApplicationThread要运行在Binder线程池(多线程)?
ApplicationThread作为App进程和system_server进程(AMS)通信的“Binder服务端”,运行在App进程的Binder线程池中——这个线程池默认会创建多个线程(而非单线程)来处理AMS发来的跨进程请求,目的是避免单个请求阻塞导致整个通信链路卡死。
ApplicationThread是ActivityThread的内部类,且实现了IApplicationThread.Stub(Binder服务端接口),它的核心职责是接收AMS发来的所有跨进程指令(启动Activity、暂停Activity、销毁Activity、配置变化等)。
如果只用单线程处理这些指令,会出现致命问题:
问题1:单线程阻塞导致所有指令卡死
比如AMS发了两个指令:
- “启动Activity A”(耗时200ms);
- “暂停Activity B”(紧急,需立即处理)。
若单线程处理:必须等“启动A”完成后,才能处理“暂停B”,可能导致Activity B无法及时暂停,出现UI卡顿、ANR甚至系统异常。
问题2:不符合Android的通信设计规范
Android框架设计时,明确要求“Binder服务端的回调方法必须运行在非主线程”——因为:
- 主线程要处理UI渲染、事件分发,若Binder请求(比如AMS的启动指令)跑在主线程,一旦请求耗时,会直接阻塞主线程,导致App卡死;
- 多线程的Binder线程池,把跨进程请求的处理和主线程解耦,保证主线程的流畅性。
ApplicationThread的Binder线程池多线程的具体表现
1. 源码级证据(ActivityThread核心逻辑)
ActivityThread的attach()方法中,会将ApplicationThread注册到AMS,同时系统会自动把ApplicationThread的回调方法分配到Binder线程池的不同线程:
// ActivityThread.java
private void attach(boolean system, long startSeq) {
// 1. 创建ApplicationThread(Binder服务端)
mAppThread = new ApplicationThread();
// 2. 获取AMS的Binder代理(客户端)
final IActivityManager mgr = ActivityManager.getService();
try {
// 3. 将ApplicationThread注册到AMS,后续AMS通过Binder调用AppThread的方法
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
// ApplicationThread的回调方法(运行在Binder线程池)
class ApplicationThread extends IApplicationThread.Stub {
// 处理AMS发来的“启动Activity”指令
@Override
public final void scheduleLaunchActivity(...) {
// 此方法运行在Binder线程池的某一个线程(非主线程)
// 所以需要通过主线程Handler转发到主线程执行
sendMessage(H.LAUNCH_ACTIVITY, r);
}
// 处理AMS发来的“暂停Activity”指令
@Override
public final void schedulePauseActivity(...) {
// 此方法可能运行在Binder线程池的另一个线程
sendMessage(H.PAUSE_ACTIVITY, r);
}
}
2. 直观现象(可通过日志验证)
在ApplicationThread的回调方法中打印线程名,会发现不同指令的线程名不同:
// 自定义ApplicationThread的回调(仅演示)
@Override
public void scheduleLaunchActivity(...) {
Log.d("Binder线程", "启动Activity的线程:" + Thread.currentThread().getName());
// 输出:Binder线程: 启动Activity的线程:Binder:1234_2
sendMessage(H.LAUNCH_ACTIVITY, r);
}
@Override
public void schedulePauseActivity(...) {
Log.d("Binder线程", "暂停Activity的线程:" + Thread.currentThread().getName());
// 输出:Binder线程: 暂停Activity的线程:Binder:1234_3
}
✅ 关键:Binder:1234_2、Binder:1234_3 代表App进程(PID=1234)的Binder线程池中的第2、3个线程,证明是多线程处理。
3. 多线程带来的问题与解决方案
Binder线程池是多线程的,意味着ApplicationThread的多个回调方法可能并发执行,这会带来线程安全问题:
- 比如:AMS同时发“启动Activity A”和“销毁Activity A”的指令,可能导致并发修改Activity状态;
- 解决方案:ApplicationThread收到指令后,统一通过主线程的Handler(mH)转发到主线程执行——主线程是单线程的,天然避免并发问题,这也是为什么你之前看到“通过Handler转发给ActivityThread”的核心原因。
核心关键点总结
- Binder线程池的本质:App进程的子线程池,专门处理其他进程(如AMS)发来的Binder请求,默认多线程(2-4个,可扩容);
- ApplicationThread的角色:作为Binder服务端,运行在这个多线程池里,接收AMS的所有跨进程指令;
- 多线程的目的:避免单个请求阻塞导致所有指令卡死,保证跨进程通信的高效性;
- 多线程的副作用:并发执行带来线程安全问题,因此需要通过主线程Handler转发指令,回到单线程处理。
简单记:Binder线程池是App的“多线程客服部”,处理外部进程的请求;ApplicationThread是客服人员,收到请求后统一交给“主线程总经理”处理,既高效又安全。
ApplicationThread 为什么不注册到 ServiceManager ?
ApplicationThread确实是Binder服务端,但它不需要注册到ServiceManager,而是通过“私有Binder通信”的方式和AMS建立绑定。
- ApplicationThread 是App进程的Binder服务端(负责接收AMS的指令);
- 并非所有Binder服务端都要注册到ServiceManager——只有“系统级全局服务”(如AMS、WMS、PMS)才需要注册到ServiceManager;
- ApplicationThread是AMS的“私有Binder服务端”:只和AMS建立一对一的Binder连接,无需全局注册,这是Android进程通信的“按需绑定”设计。
1. 先搞懂:ServiceManager的核心作用(为什么不是所有服务都要注册)
ServiceManager是Android系统的“Binder服务注册表”,核心职责是:
- 管理系统级、全局可访问的Binder服务(如AMS、WMS、PMS);
- 提供“服务名→Binder对象”的查询能力,让任意进程能通过服务名找到对应的Binder服务端。
两类Binder服务端的区别(关键)
| 服务端类型 | 是否注册到ServiceManager | 适用场景 | 例子 |
|---|---|---|---|
| 系统级全局服务 | 是 | 所有进程都需要访问的服务 | AMS、WMS、PMS |
| 进程间私有Binder服务 | 否 | 两个进程之间的一对一通信 | ApplicationThread、自定义IPC |
通俗类比
把ServiceManager比作“全国企业黄页”:
- AMS、WMS这类系统服务是“全国连锁企业”,需要登黄页,让所有进程(企业)都能找到;
- ApplicationThread是“AMS的专属供应商”:只和AMS打交道,不需要登黄页,只要AMS知道它的联系方式就行。
2. ApplicationThread作为Binder服务端,如何和AMS建立通信?
你疑惑的“为什么不注册到ServiceManager”,核心是ApplicationThread和AMS的通信是“反向绑定”,而非“全局注册”,完整流程如下:
步骤1:AMS是“全局注册的Binder服务端”(先有基础)
- AMS(ActivityManagerService)运行在system_server进程,启动时会把自己注册到ServiceManager,服务名是
"activity"; - 任意App进程都能通过
ServiceManager.getService("activity")获取AMS的Binder代理(客户端)——这是App能主动调用AMS的基础。
步骤2:App进程创建ApplicationThread(Binder服务端)
ActivityThread的attach()方法中,会创建ApplicationThread实例(实现了IApplicationThread.Stub,即Binder服务端):
// ActivityThread.java
private void attach(boolean system, long startSeq) {
// 1. 创建Binder服务端:ApplicationThread
mAppThread = new ApplicationThread();
// 2. 获取AMS的Binder客户端代理(从ServiceManager拿到)
final IActivityManager ams = ActivityManager.getService(); // 本质是ServiceManager.getService("activity")
try {
// 3. 核心操作:把ApplicationThread的Binder对象传给AMS
ams.attachApplication(mAppThread, startSeq);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
步骤3:AMS保存ApplicationThread的Binder代理(关键)
当App进程调用ams.attachApplication(mAppThread)时:
mAppThread是App进程的Binder服务端对象,跨进程传递时会被Binder驱动自动转换成AMS进程中的Binder代理对象;- AMS收到这个代理对象后,会把它和当前App进程的信息(PID、包名等)绑定,保存到自己的内存中(比如
mProcessNames、mActiveApplications等容器); - 此后AMS要给App发指令(如启动Activity),直接通过这个保存的代理对象调用ApplicationThread的方法即可。
步骤4:AMS→App的指令流转(反向调用)
graph TD
A[AMS system_server进程] -->|持有ApplicationThread的Binder代理| B[Binder驱动]
B -->|转发到App进程| C[ApplicationThread Binder服务端]
C -->|运行在Binder线程池| D[通过Handler转发到主线程]
D -->|执行生命周期| E[ActivityThread]
3. 码级验证:attachApplication的核心逻辑
我们看AMS的attachApplication()方法(简化版),就能明白它如何保存ApplicationThread的代理:
// ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread app, long startSeq) {
// 1. app是ApplicationThread的Binder代理对象(来自App进程)
if (app == null) {
throw new IllegalArgumentException("app is null");
}
// 2. 获取App进程的信息(PID、包名等)
final int pid = Binder.getCallingPid();
final String processName = getProcessNameByPid(pid);
// 3. 把ApplicationThread代理和进程信息绑定,保存到AMS内存中
ProcessRecord appProcess = getProcessRecordLocked(pid, processName);
appProcess.appThread = app; // 关键:保存代理对象
// 4. 后续AMS给App发指令时,直接用appProcess.appThread调用
// 比如启动Activity:appProcess.appThread.scheduleLaunchActivity(...)
}
✅ 关键:AMS通过attachApplication()拿到了ApplicationThread的Binder代理,相当于“保存了App进程的通信地址”,后续无需ServiceManager,直接一对一通信。
4. 为什么ApplicationThread不需要注册到ServiceManager?
- 无全局访问需求:ApplicationThread只需要和AMS通信,其他进程(如电话、相机)根本不需要访问它,注册到ServiceManager完全没必要;
- 降低系统开销:ServiceManager是全局单点服务,注册的服务越多,查询和维护成本越高;私有Binder通信按需绑定,更高效;
- 安全可控:只让AMS持有ApplicationThread的代理,避免其他恶意进程通过ServiceManager获取App的Binder服务端,提升安全性;
- 生命周期匹配:ApplicationThread的生命周期和App进程一致,App退出后代理自动失效,无需ServiceManager做额外清理。
5. 核心关键点总结
- ApplicationThread 是App进程的Binder服务端,但它是AMS的“私有服务端”,而非全局服务;
- 只有系统级全局服务(AMS、WMS)需要注册到ServiceManager,私有Binder服务只需“按需绑定”;
ActivityThread.attach()的核心是:把ApplicationThread的Binder对象传给AMS,让AMS保存其代理,从而建立“AMS→App”的反向通信链路;- 整个过程的本质是:App通过ServiceManager找到AMS,再把自己的Binder服务端代理交给AMS,实现双向通信。
简单记:
- ServiceManager管“全局服务”(AMS、WMS);
- 私有Binder管“一对一通信”(AMS↔ApplicationThread);
- ApplicationThread不登“黄页”,只给AMS留“私人联系方式”。
核心 IPC 交互总结(进程间调用关系)
| 调用方向 | IPC 方式 | 核心目的 | 关键接口 / 对象 |
|---|---|---|---|
| Launcher 进程 → SystemServer(AMS) | Binder(C/S) | 请求启动目标 App | AMS.startActivity() |
| SystemServer(AMS) → Zygote 进程 | Socket | 请求孵化新的 App 进程 | ZygoteProcess.forkAndSpecialize() |
| App 进程 → SystemServer(AMS) | Binder(C/S) | 注册 App 进程,告知 AMS 已就绪 | ApplicationThread.attachApplication() |
| SystemServer(AMS) → App 进程 | Binder(C/S) | 下发启动 Activity 的指令 | ApplicationThread.scheduleLaunchActivity() |
Binder 的核心作用:
Binder 是 Android 中最核心的 IPC 机制,相比 Socket / 管道 / 共享内存,具有
性能高、权限管控细、支持跨进程对象传递
的优势,上述流程中除了 AMS 向 Zygote 的调用(Zygote 是 root 权限,Binder 不支持跨 UID 调用),其余进程间通信均基于 Binder。
冷启动与热启动的核心区别:
热启动时,App 进程已存在,无需 Zygote 孵化进程的步骤,直接执行 “AMS 向 App 进程下发启动 Activity 指令” 阶段,启动速度远快于冷启动。
启动优化的核心切入点:
- 减少 Application.onCreate () 中的耗时操作(如初始化 SDK);
- 延迟加载非核心组件,优先渲染界面;
- 优化布局层级,减少首屏绘制时间。
App 进程启动 Activity ,这个Activity是App进程创建的 还是AMS创建的?
Activity 是由 App 进程自己创建的,AMS 仅负责下发 “启动指令”,不参与 Activity 的实例化过程。
- Activity 实例的创建者:App 进程(ActivityThread)通过类加载器 + 构造方法创建,全程在 App 进程内完成;
- AMS 的核心作用:仅负责 “指令下发” 和 “状态管控”,不参与任何实例化逻辑;
- 核心边界:进程隔离决定了 SystemServer 进程(AMS)无法跨进程创建 App 进程内的对象,这是 Android 系统架构的底层设计原则。
核心结论拆解
1. AMS 的角色:“指挥者” 而非 “创建者”
AMS(SystemServer 进程中)的核心作用是:
- 校验启动权限、维护任务栈、判断进程状态;
- 向 App 进程下发 “启动指定 Activity” 的指令(通过 Binder IPC 调用
ApplicationThread.scheduleLaunchActivity()); - 传递启动所需的元数据(如 Intent、Activity 组件信息、窗口配置);
- 但绝不会直接创建 Activity 实例—— 因为 Activity 是 App 的业务组件,必须运行在 App 进程的虚拟机中,AMS 所在的 SystemServer 进程无法访问 App 的类加载器、资源文件,也无权创建 App 内的对象。
2. App 进程的角色:“执行者”+“创建者”
App 进程收到 AMS 的启动指令后,完整掌控 Activity 的创建流程:
ApplicationThread(App 进程内的 Binder 对象)接收到 AMS 的指令后,通过主线程 Handler 将请求转发给 ActivityThread;- ActivityThread 调用
performLaunchActivity()方法,核心逻辑包括:- 通过
ClassLoader加载目标 Activity 的类(App 进程自己的类加载器,加载 Apk 中的 Activity.class); - 调用 Activity 的构造方法(
new Activity()),创建实例; - 执行
attach()方法,绑定 Context、Window 等核心资源; - 依次调用
onCreate()/onStart()/onResume()等生命周期方法。
- 通过
关键代码佐证(Android 源码层面)
1. AMS 侧:仅下发指令,不创建实例
// SystemServer进程 - AMS源码片段
private final boolean startProcessLocked(...) {
// 向Zygote请求孵化App进程,仅传递启动参数
zygoteProcess.startProcess(...);
// 向已就绪的App进程下发启动Activity指令
app.thread.scheduleLaunchActivity(...); // 仅传递元数据,无创建逻辑
}
2. App 进程侧:主动创建 Activity 实例
// App进程 - ActivityThread源码片段
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity activity = null;
try {
// 1. 加载Activity类(App进程的类加载器)
java.lang.ClassLoader cl = appContext.getClassLoader();
// 2. 创建Activity实例(核心!App进程内执行new操作)
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
// 3. 初始化Activity(绑定Context、执行生命周期)
activity.attach(...);
mInstrumentation.callActivityOnCreate(activity, r.state);
} catch (Exception e) {
// 异常处理
}
return activity;
}
为什么 Activity 必须由 App 进程创建?
- 进程隔离:Android 的进程是独立的沙箱,SystemServer 进程(AMS)无法访问 App 进程的内存空间、类加载器、资源文件;
- 类加载限制:Activity 是 App 的自定义类,只有 App 进程的
PathClassLoader能加载 Apk 中的 Activity.class,AMS 所在的 SystemServer 进程使用的是系统类加载器(BootClassLoader/SystemClassLoader),无法加载 App 的业务类; - 生命周期管控:Activity 的生命周期(如
onCreate())需要访问 App 的 Application、资源、组件,这些都仅存在于 App 进程中,AMS 无法模拟。
影响启动速度的核心环节
- Zygote 预加载:系统预加载框架类和资源,减少 App 进程初始化时间,开发者无法干预。
- Application.onCreate():主线程耗时操作(如 SDK 初始化)是启动延迟的主要原因,需异步 / 延迟处理。
- Activity.onCreate():
setContentView()加载复杂布局(如嵌套层级多、大图片)会增加绘制耗时,需简化布局。 - 首次绘制(First Draw):只有完成首次绘制,用户才能看到界面,之前的 “黑白屏” 是系统的临时过渡窗口(见「App 黑白屏问题」)。
热启动与温启动流程(简化版)
冷启动是 “全流程”,热启动和温启动因进程已存在,流程更短:
| 启动类型 | 核心特点 | 流程简化 | 耗时对比 |
|---|---|---|---|
| 热启动 | 进程、Application、Activity 均存在 | 点击图标 → AMS 唤起 Activity → onResume() | 最快(< 500ms) |
| 温启动 | 进程、Application 存在,Activity 需重建 | 点击图标 → 重建 Activity(onCreate() → onResume()) | 中等(500ms~1s) |
| 冷启动 | 进程、Application、Activity 均需创建 | 全流程(6 个阶段) | 最慢(1~3s) |
热启动流程
热启动核心定义
热启动是指:App 进程已存在(如退到后台但未被系统杀死),用户从 Launcher / 最近任务列表点击图标重新打开 App 的场景。
核心特征:无需新建进程、无需重新初始化 Application,仅需恢复 / 重启目标 Activity,启动速度通常比冷启动快 10 倍以上。
热启动完整流程(点击 Launcher 图标开始)
阶段 1:Launcher 进程发起启动请求(同冷启动,但参数有差异)
用户点击 App 图标,Launcher 的
onClick()触发,封装启动 Intent(包含FLAG_ACTIVITY_NEW_TASK等标志);Launcher 进程 → SystemServer 进程(AMS)
(Binder IPC):
- 调用
AMS.startActivity(),传递启动参数; - 核心差异:Intent 中会携带 “目标 App 进程已存在” 的隐含信息,AMS 无需触发进程孵化流程。
- 调用
阶段 2:AMS 校验进程状态,直接下发启动指令
AMS 校验:
- 检查目标 App 的进程状态(通过 PID / 包名判定进程已存活);
- 校验 Activity 任务栈:若目标 Activity 已在栈中(如退后台未销毁),则标记 “恢复 Activity”;若已销毁,则标记 “重新创建 Activity”;
- 无需调用 PMS 重新解析 Manifest(冷启动需解析,热启动直接复用缓存的组件信息);
SystemServer 进程(AMS) → App 进程
(Binder IPC):
- 调用 App 进程中
ApplicationThread.scheduleLaunchActivity()(恢复 Activity)或scheduleResumeActivity()(重启 Activity); - 核心数据:仅传递 Activity 栈信息、窗口配置,无需传递进程初始化参数。
- 调用 App 进程中
阶段 3:App 进程恢复 / 重建 Activity,绘制界面
App 进程接收指令(无进程初始化步骤):
ApplicationThread通过主线程 Handler 将指令转发给 ActivityThread;- 核心差异:无需执行
Application.attachBaseContext()/onCreate()(Application 已初始化),无需创建新的 Looper / 主线程;
Activity 处理逻辑(分两种场景):
场景 核心操作 Activity 未销毁(退后台) ActivityThread 调用 performResumeActivity(),执行onRestart()→onStart()→onResume(),直接恢复界面;Activity 已销毁(栈内重建) ActivityThread 调用 performLaunchActivity()创建新 Activity 实例(仅创建 Activity,不初始化 Application),执行onCreate()→onStart()→onResume();界面绘制:
- 复用已加载的布局资源、缓存的图片 / 数据,快速完成 Surface 渲染;
- 无冷启动的 “应用初始化→资源加载” 耗时步骤,首屏秒出。
热启动 vs 冷启动核心差异对比
| 流程节点 | 冷启动 | 热启动 |
|---|---|---|
| 进程状态 | 无进程,需 Zygote 孵化 | 进程已存在,直接复用 |
| AMS 核心操作 | 孵化进程 + 下发启动指令 | 直接下发恢复 / 重启指令 |
| IPC 交互 | 4 次(Launcher→AMS→Zygote→App→AMS→App) | 2 次(Launcher→AMS→App) |
| App 初始化 | 执行 Application 生命周期 | 不执行 Application 生命周期 |
| Activity 创建 | 全新创建(类加载 + 构造方法) | 恢复(复用实例)或重建(仅 Activity) |
| 资源加载 | 重新加载所有资源 | 复用已缓存的资源 |
| 启动耗时 | 数百 ms~ 数秒 | 数十 ms |
核心 IPC 交互总结(热启动仅 2 次 Binder 调用)
| 调用方向 | IPC 方式 | 核心目的 |
|---|---|---|
| Launcher 进程 → SystemServer(AMS) | Binder | 请求启动 App(告知进程已存在) |
| SystemServer(AMS) → App 进程 | Binder | 下发恢复 / 重启 Activity 的指令 |
热启动优化的核心切入点
- 避免 Activity 频繁销毁:合理设置
launchMode(如singleTop/singleTask),减少栈内重建; - 缓存核心资源:首屏图片、网络数据缓存到内存,热启动时直接复用;
- 优化
onRestart()/onResume():避免在这些生命周期中执行耗时操作(如网络请求、大量数据解析); - 减少后台进程被杀死:通过合理的保活策略(如前台服务、WorkManager)降低进程被杀概率,维持热启动状态。
温启动流程
- 温启动的核心是 “进程存活 + Activity 重建”,跳过了冷启动的 “进程孵化 + Application 初始化”,但需执行 Activity 的全新创建流程;
- IPC 交互仅 2 次 Binder 调用(同热启动),但 Activity 创建逻辑同冷启动(无 Application 初始化);
- 温启动优化的关键是 “复用进程内缓存 + 减少 Activity 重建后的耗时操作”,核心目标是向热启动的速度靠拢。
温启动核心定义
温启动(Warm Start):App 进程仍存活,但目标 Activity 已被销毁(如用户返回退出 Activity、系统回收 Activity 实例),用户再次点击图标启动 App 的场景。
核心特征:
- ✅ App 进程已存在(无需 Zygote 孵化);
- ❌ 目标 Activity 实例已销毁(需重新创建);
- ❌ Application 无需重新初始化(进程存活,Application 实例仍在);
- 启动速度:介于冷启动(慢)和热启动(快)之间,通常比冷启动快 50% 以上。
温启动完整流程(点击 Launcher 图标开始)
阶段 1:Launcher 进程发起启动请求(同冷 / 热启动)
用户点击 App 图标,Launcher 触发
onClick(),封装启动 Intent(含包名、默认启动 Activity);Launcher 进程 → SystemServer 进程(AMS)
(Binder IPC):
- 调用
AMS.startActivity(),传递启动参数; - 核心差异:AMS 校验后判定 “进程存活,但目标 Activity 无实例”,触发 “重建 Activity” 流程。
- 调用
阶段 2:AMS 校验状态,下发 “重建 Activity” 指令
AMS 核心校验:
- 检查 App 进程状态:PID 有效、进程未被杀死(复用已有进程);
- 检查 Activity 任务栈:目标 Activity(默认启动页)已从栈中销毁(如用户执行
finish()、系统因内存不足回收); - 复用缓存的 Manifest 信息(无需重新解析 Apk),仅重新确认默认启动 Activity;
SystemServer 进程(AMS) → App 进程
(Binder IPC):
- 调用 App 进程中
ApplicationThread.scheduleLaunchActivity()(注意:是scheduleLaunchActivity而非热启动的scheduleResumeActivity); - 核心数据:传递 Activity 组件信息、Intent、任务栈配置,无进程初始化参数。
- 调用 App 进程中
阶段 3:App 进程重建 Activity,绘制界面
App 进程接收指令(无进程 / Application 初始化步骤):
ApplicationThread通过主线程 Handler 将指令转发给 ActivityThread;- 核心差异:
- 无需执行
Application.attachBaseContext()/onCreate()(Application 实例已存在); - 无需初始化主线程 Looper、类加载器等(进程存活,这些资源已就绪);
- 无需执行
Activity 重建流程:
ActivityThread 调用
performLaunchActivity()(同冷启动的 Activity 创建逻辑,但无 Application 初始化):- 步骤 1:通过 App 进程的类加载器加载 Activity 类(复用已有类加载器);
- 步骤 2:创建 Activity 实例(
new Activity()); - 步骤 3:执行 Activity 生命周期:
onCreate()→onStart()→onResume();
界面绘制:
- 复用进程内已缓存的资源(如图片、布局文件、网络数据缓存);
- 通过 WindowManagerService(WMS)渲染界面,完成启动。
冷 / 温 / 热启动核心差异对比
| 维度 | 冷启动 | 温启动 | 热启动 |
|---|---|---|---|
| 进程状态 | 无进程,需 Zygote 孵化 | 进程存活 | 进程存活 |
| Application 状态 | 需重新创建 + 执行 onCreate () | 已存在,不执行 onCreate () | 已存在,不执行 onCreate () |
| Activity 状态 | 全新创建 | 重建(实例已销毁) | 恢复(实例未销毁) |
| 核心 IPC 次数 | 4 次(Launcher→AMS→Zygote→App→AMS→App) | 2 次(Launcher→AMS→App) | 2 次(Launcher→AMS→App) |
| 关键调用方法 | AMS.startProcess ()(孵化进程) | AMS.scheduleLaunchActivity() | AMS.scheduleResumeActivity() |
| 启动耗时 | 最长(数百 ms~ 数秒) | 中等(数十 ms~ 百 ms) | 最短(数 ms~ 数十 ms) |
| 典型场景 | 首次启动、进程被系统杀死后启动 | 进程存活但 Activity 已销毁 | 退后台未杀进程,直接恢复 |
温启动优化的核心切入点
- 缓存 Activity 关键数据:在
onSaveInstanceState()中保存 Activity 的核心数据(如表单内容、列表滚动位置),温启动时在onCreate()中恢复,避免重复请求网络 / 解析数据; - 复用进程内缓存资源:将图片、网络数据、配置信息缓存到 Application 或内存缓存中,重建 Activity 时直接复用,减少
onCreate()耗时; - 避免非必要的 Activity 销毁:合理设计返回逻辑,避免用户误操作导致核心 Activity 被
finish(); - 优化
onCreate()逻辑:将非首屏必要的初始化操作(如 SDK 初始化、埋点)延迟到onResume()或异步执行,缩短温启动首屏时间。
关键补充:系统如何判定 “是否温启动”?
Android 系统通过两个维度判定:
- 进程存活判定:AMS 维护 “进程列表”,通过 PID 和进程状态(
PROCESS_STATE_TOP/PROCESS_STATE_CACHED)判断进程是否存活; - Activity 实例判定:AMS 维护 “任务栈(TaskStack)” 和 “ActivityRecord”,每个 ActivityRecord 对应一个 Activity 实例,若 ActivityRecord 已被移除(
finish()/ 系统回收),则判定需重建。
Activity 启动流程
Activity 启动是 App 启动的核心子流程,跨进程通信是核心特点,分为 6 步(以启动新 Activity 为例):
应用层发起请求:当前 Activity 调用
startActivity(Intent)→ 最终调用Instrumentation.execStartActivity()。Binder 跨进程调用 AMS:
Instrumentation通过 Binder 向 SystemServer 进程的 AMS 发送启动请求。AMS 权限与栈管理:
- AMS 检查权限、验证 Intent 合法性;
- 根据
launchMode决定创建新实例或复用已有实例; - 向 Zygote 请求创建进程(若进程未启动)。
AMS 通知 App 进程创建 Activity:
- AMS 通过 Binder 向 App 进程的 ApplicationThread 发送创建 Activity 的指令。
线程切换与 Activity 实例化:
- ApplicationThread 接收到指令后,通过 H(Handler) 将任务转发到主线程(ActivityThread);
- ActivityThread 通过
ClassLoader创建 Activity 实例; - 依次调用
onCreate()→onStart()→onResume()。
AMS 同步状态:Activity 生命周期执行完成后,ApplicationThread 向 AMS 报告状态,AMS 更新任务栈信息。
核心系统组件详解
1. Zygote(孵化器进程)
核心功能
- 进程孵化器:是 Android 系统中所有 App 进程和 SystemServer 进程的父进程,由
init进程启动(解析init.rc配置文件)。 - 预加载资源:启动时会预加载 Android 核心类库、系统资源(如主题、字符串)、初始化 Dalvik/ART 虚拟机,避免每个 App 进程重复初始化,提升进程创建速度。
- 进程创建:通过
fork()系统调用创建子进程(App 进程或 SystemServer 进程),采用写时复制机制,减少内存开销。
关键特点
- 自身是一个特殊的 Dalvik/ART 进程,不执行具体业务逻辑,仅负责孵化进程。
- 通过
socket与 SystemServer 通信,接收创建进程的请求。
2. ServiceManager(系统服务管家)
核心功能
- 系统服务注册中心:是 Android 系统的「Binder 大管家」,负责管理所有系统服务的注册与查询。
- 服务注册:所有系统服务(如 AMS、WMS、PMS)启动后,都会向 ServiceManager 注册(通过
addService()方法)。 - 服务查询:客户端(如 App 进程)需要使用系统服务时,通过
getService()向 ServiceManager 查询,获取服务的 Binder 代理对象。
关键特点
- 由
init进程启动,是第一个启动的系统服务,运行在 SystemServer 进程启动前。 - 自身不提供业务服务,仅负责「服务的注册与转发」。
3. SystemServer(系统服务进程)
核心功能
- 系统服务的宿主进程:是 Android 系统的「核心服务容器」,几乎所有核心系统服务都运行在该进程中(如 AMS、WMS、PMS、PowerManagerService 等)。
- 启动与管理系统服务:由 Zygote 进程
fork()生成,启动后会依次启动各类系统服务,并将服务注册到 ServiceManager。 - 系统核心调度:协调各系统服务之间的通信,是 App 进程与系统服务交互的「中转站」。
启动的核心服务分类
| 服务类型 | 代表服务 | 核心作用 |
|---|---|---|
| 生命周期管理 | AMS(ActivityManagerService) | 管理 Activity 生命周期、进程调度 |
| 窗口管理 | WMS(WindowManagerService) | 管理窗口的显示、层级、大小 |
| 包管理 | PMS(PackageManagerService) | 管理 App 安装、卸载、权限 |
| 电源管理 | PowerManagerService | 管理设备电源状态、休眠 / 唤醒 |
4. PowerManagerService(电源管理服务)
核心功能
设备电源状态管理:是 Android 系统中负责电源策略、休眠唤醒、亮度调节的核心服务,运行在 SystemServer 进程。
核心职责:
- 监听电源键、电池状态、传感器事件(如距离传感器);
- 管理设备状态(开机、休眠、唤醒、关机);
- 调节屏幕亮度、控制背光开关;
- 实现电源节能策略(如屏幕自动熄灭、进程休眠)。
对外接口:通过
PowerManager类向应用层提供 API(如唤醒屏幕、设置屏幕亮度)。
核心组件的关系与执行先后顺序
1. 组件之间的依赖关系
init 进程 → ServiceManager → Zygote → SystemServer → 各类系统服务(含 PowerManagerService)→ App 进程
init是根进程:Android 系统启动后,内核首先启动init进程,它是所有进程的祖先。ServiceManager是服务管家:由init启动,为后续系统服务提供注册 / 查询能力。Zygote是孵化器:由init启动,负责孵化 SystemServer 和所有 App 进程。SystemServer是服务容器:由 Zygote 孵化,启动并管理 PowerManagerService 等所有系统服务,且将服务注册到 ServiceManager。PowerManagerService是子服务:运行在 SystemServer 进程内部,依赖 SystemServer 提供的运行环境,同时通过 ServiceManager 对外提供服务。
2. 严格的执行先后顺序(系统启动阶段)
系统启动时,组件的启动顺序是固定且不可逆的,具体步骤如下:
内核启动:Android 设备开机后,首先加载内核,初始化硬件驱动。
启动
init进程:内核启动后,启动init进程,init解析init.rc配置文件。启动
ServiceManager:init进程根据配置启动ServiceManager,使其进入等待状态,准备接收服务注册请求。启动
Zygote进程:init进程启动Zygote进程,Zygote 预加载核心类库和资源,初始化虚拟机,监听socket端口。Zygote 孵化
SystemServer进程:- Zygote 通过
fork()创建 SystemServer 进程; - SystemServer 进程启动后,初始化主线程,依次启动各类系统服务(包括 PowerManagerService、AMS、WMS 等)。
- Zygote 通过
系统服务注册到
ServiceManager:每个系统服务启动后,都会调用ServiceManager.addService()完成注册。PowerManagerService启动:作为 SystemServer 启动的服务之一,启动后注册到 ServiceManager,开始管理设备电源状态。启动 Launcher 进程:SystemServer 启动完成后,AMS 会启动 Launcher 进程(桌面应用),用户可点击图标启动 App。
Zygote 孵化 App 进程:用户启动 App 时,AMS 通过 socket 通知 Zygote,Zygote
fork()生成 App 进程。
3. 组件协作示例(App 启动时)
当用户启动 App 时,核心组件的协作流程:
用户点击 Launcher → Launcher 通过 ServiceManager 获取 AMS 代理 → AMS 通过 socket 通知 Zygote → Zygote fork App 进程 → App 进程通过 ServiceManager 获取 PowerManagerService 代理(若需电源相关操作)
总结
- App 启动流程:用户触发 → AMS 请求 → Zygote 孵化进程 → ActivityThread 初始化 → Application 与 Activity 启动 → 界面显示。
- Activity 启动流程:应用层请求 → Binder 调用 AMS → AMS 管理栈与进程 → App 进程线程切换 → Activity 实例化与生命周期执行。
- 核心组件关系:
init是根进程,ServiceManager是服务管家,Zygote是进程孵化器,SystemServer是服务容器,PowerManagerService是 SystemServer 内的子服务。 - 执行先后:
init→ServiceManager→Zygote→SystemServer→PowerManagerService→ App 进程。