一、引言:为什么你必须搞懂 AMS?
很多 Android 开发者都会遇到这些问题:
- 为什么
startActivity()有时候会失败? - 应用在后台为什么会被“莫名其妙”杀掉?
- 多 Activity 切换为什么会有奇怪的生命周期顺序?
- ANR 到底是谁判定的?
这些问题的背后,其实都绕不开一个核心系统服务——AMS(ActivityManagerService) 。
👉 可以这么说:
只要涉及“应用进程”和“组件生命周期”,背后几乎都有 AMS 的影子。
但问题是:
❗ 大多数人只知道 AMS “很重要”,却说不清它到底“管什么”。
这篇文章,我们就从工程实战的角度,把 AMS 的职责边界讲清楚。
二、背景知识:AMS 在系统中的位置
在 Android 启动过程中:
- Zygote fork 出 SystemServer
- SystemServer 启动各种系统服务
- AMS 在这里被创建并注册到 Binder
// SystemServer.java
mActivityManagerService = ActivityManagerService.Lifecycle.startService(...)
AMS 的本质是:
一个运行在 SystemServer 进程中的“应用管理中心”
它通过 Binder 对外提供能力,客户端入口通常是:
val am = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
⚠️ 注意:
ActivityManager是客户端代理- 真正干活的是 AMS(系统进程)
三、核心原理解析:AMS 到底管什么?
一句话总结:
AMS 负责管理“四大组件 + 应用进程 + 调度策略”
我们拆开讲。
1️⃣ 管 Activity —— 页面调度核心
AMS 最核心的职责之一就是:
管理 Activity 的启动、切换、生命周期
比如:
startActivity()- Activity 栈(Task / BackStack)
- 生命周期分发(onResume/onPause)
📌 核心结构:
ActivityRecord:一个 Activity 实例Task:任务栈ActivityStack(老版本)/TaskDisplayArea
📌 启动流程(简化):
App -> startActivity()
-> Instrumentation
-> ActivityTaskManagerService(ATMS)
-> AMS(调度)
-> 启动目标进程(如果不存在)
-> scheduleLaunchActivity
👉 Android 10 之后:
- Activity 管理被拆到 ATMS
- 但 AMS 仍负责进程 + 调度
2️⃣ 管进程 —— 生死大权在手
AMS 还负责:
应用进程的创建、优先级管理、回收
📌 核心类:
ProcessRecordProcessList
📌 关键机制:
🔹 进程优先级(OOM_ADJ)
AMS 会根据组件状态给进程打分:
| 类型 | 优先级 |
|---|---|
| 前台 Activity | 最高 |
| 可见 Activity | 较高 |
| Service | 中 |
| 后台进程 | 低 |
| 空进程 | 最低 |
👉 当内存不足:
AMS 会杀掉低优先级进程
🔹 冷启动的本质
startActivity
-> AMS 检查进程是否存在
-> 不存在 → fork 新进程(通过 Zygote)
-> attachApplication
-> 启动 Activity
👉 所以:
冷启动慢,本质是“AMS + Zygote + 进程初始化”的成本
3️⃣ 管 Service —— 后台能力调度
AMS 还负责:
startServicebindService- 前台服务限制(Android 8+)
📌 典型问题:
为什么后台启动 Service 会崩?
答案:
👉 AMS 限制了后台执行(Background Execution Limits)
4️⃣ 管 Broadcast —— 系统消息分发
AMS 负责:
- 广播注册
- 广播发送
- 有序广播调度
📌 核心类:
BroadcastRecordBroadcastQueue
📌 特点:
- 支持串行 / 并行
- 控制 ANR(超时)
5️⃣ 管 ANR —— 谁来“判死刑”?
很多人以为 ANR 是系统自动检测的,其实:
ANR 的判定和处理,核心在 AMS
📌 场景:
- Activity 5 秒无响应
- Broadcast 10 秒
- Service 20 秒
📌 机制:
AMS -> InputDispatcher / BroadcastQueue
-> 超时检测
-> dump stack
-> 弹 ANR 对话框
四、源码 / 机制分析
我们看一个典型调用链:
🔍 startActivity 调用链
startActivity(intent)
↓
Instrumentation.execStartActivity()
↓
ActivityTaskManager.getService().startActivity()
↓
ActivityTaskManagerService.startActivity()
↓
ActivityStarter.execute()
↓
RootWindowContainer.resumeFocusedTasksTopActivities()
↓
AMS 启动进程(如果需要)
👉 关键点:
- AMS 不直接管 UI
- 它是“调度者 + 决策者”
五、实战示例:分析一次冷启动
我们写一个简单 Activity:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("AMS", "onCreate")
}
override fun onResume() {
super.onResume()
Log.d("AMS", "onResume")
}
}
然后用 adb 观察:
adb shell am start -n com.example/.MainActivity
你会看到:
Start proc 12345:com.example/u0a123 for activity
👉 这行日志来自 AMS!
说明:
AMS 负责决定是否创建进程
🔍 冷启动关键阶段
1. AMS 收到启动请求
2. 检查进程是否存在
3. fork 进程(Zygote)
4. attachApplication
5. scheduleLaunchActivity
6. ActivityThread 执行生命周期
👉 你做启动优化,其实就是在优化:
- AMS 调度链路
- Application 初始化
- 主线程阻塞
六、常见误区 / 踩坑总结
❌ 误区 1:AMS = Activity 管理器
错误!
👉 实际上:
AMS 是“应用生命周期管理器”
包括:
- Activity
- Service
- Broadcast
- Process
❌ 误区 2:Activity 生命周期由系统自动调用
不完全对。
👉 实际:
AMS 决定“什么时候调用”,ActivityThread 执行
❌ 误区 3:进程被杀是随机的
错!
👉 实际:
AMS 按优先级(OOM_ADJ)精确控制
❌ 误区 4:ANR 是 UI 卡顿导致的
不准确。
👉 真相:
ANR 是“AMS 检测到超时”
七、性能优化 & 最佳实践
🚀 1. 冷启动优化要盯 AMS
重点:
- 减少 Application 初始化时间
- 避免主线程阻塞
- 延迟初始化
🚀 2. 合理使用前台服务
startForegroundService(intent)
否则:
👉 AMS 直接抛异常
🚀 3. 避免滥用广播
问题:
- 阻塞 BroadcastQueue
- 导致 ANR
优化:
- 使用 WorkManager 替代
🚀 4. 控制进程优先级
例如:
startForeground(...)
👉 提升进程存活率
🚀 5. 理解“进程重启”
当你看到:
Process com.xxx has died
👉 本质是:
AMS 决定杀掉 + 重新拉起
八、总结:AMS 的本质是什么?
最后用一句话收尾:
AMS 是 Android 的“应用调度中枢”,负责决定:谁能活、谁先跑、谁该死。
你可以这样理解它:
🧠 类比操作系统:
| 角色 | 类比 |
|---|---|
| AMS | 操作系统调度器 |
| Activity | 前台窗口 |
| Service | 后台任务 |
| Process | 进程 |
📌 核心要点回顾
- AMS 管的不只是 Activity,而是整个应用生命周期
- 进程管理是它最核心的能力之一
- ANR、本质调度、后台限制,都由它控制
- 优化 App,本质是在“和 AMS 打交道”