进程与内存管理全景:Android 如何决定谁活着、谁有内存
2026/8/9大约 3 分钟进程与内存管理Android 14进程内存oom_adj
进程与内存管理全景:Android 如何决定谁活着、谁有内存
Android 的低内存决策不能只看某个进程占了多少内存。AMS 先根据组件状态计算进程优先级, lmkd 再结合压力信号与候选占用选择回收目标;cgroup、Zygote 和 ART 分别影响记账与用量。
进程优先级与内存占用是两条轴
| 常见误解 | 正确理解 |
|---|---|
| 内存不足时会“谁先申请谁先死” | 系统按进程优先级(oom_adj)决定杀谁,前台应用最安全 |
| 杀进程是内核的 OOM Killer 在做 | Android 主要靠用户空间的 lmkd 主动回收,内核 OOM 是兜底 |
| 每个进程的内存互相独立、完全复制 | Zygote fork + 写时复制让子进程共享预加载的类与资源 |
核心结论
- 进程优先级由 AMS 按组件状态计算,写入 oom_adj(进程可见为 oom_score_adj)。
- lmkd 监听内存压力,从最低优先级开始杀进程,是低内存回收的主力。
- cgroup 把进程分组记账,内核按组施加内存限制与统计。
- Zygote fork + 写时复制让应用共享预加载内存,显著降低启动与内存成本。
- ART 管理 Java 堆,GC 与堆配置决定应用能申请多少内存、什么时候回收。
全景:一次低内存事件如何走完全链
逐步解释:
- 进程创建:应用进程由 Zygote fork 而来,预加载的类与资源通过写时复制共享。
- 运行期记账:AMS 计算优先级写入 oom_score_adj,进程按分组进入 cgroup。
- 内存回收:ART 管理 Java 堆,先由 GC 回收无用对象。
- 压力来临:lmkd 收到内存压力信号,按 oom_adj 从低到高挑选进程。
- 杀进程:释放内存后系统回到稳定状态,前台进程尽可能不受影响。
这条链路与 AMS 生命周期 的进程管理章节互相印证:AMS 决定“谁值得活着”, lmkd 决定“谁先走”。
常用在哪些地方
按排查频率排列:
- 后台应用被杀、进程重启:查 oom_adj 与 lmkd 日志。
- 内存不足、卡顿、OOM:查 meminfo 与内存压力信号。
- 应用堆大小限制:查 ART 堆配置与 largeHeap。
- 进程创建慢:查 Zygote fork 与预加载。
- 内存泄漏排查:查 native heap、Java heap 与 hprof。
验证与排障
环境:开发设备或模拟器;部分命令需要 root。
adb shell cat /proc/meminfo
adb shell dumpsys meminfo
adb shell cat /proc/<pid>/oom_score_adj
adb logcat -v threadtime | grep -E "lmkd|lowmemorykiller|am_kill"/proc/meminfo 看系统内存水位;dumpsys meminfo 看各进程占用;oom_score_adj 看单个 进程优先级;logcat 里的 lmkd/am_kill 记录杀进程决策。排障细节在系列末章展开。
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
OomAdjuster.java | oom_adj 计算 | 进程优先级 |
system/memory/lmkd/ | lmkd 主循环 | 低内存杀进程 |
system/core/libprocessgroup/ | cgroup 分组 | 进程记账 |
Zygote.java | fork 入口 | 进程创建 |
art/runtime/gc/ | 堆与 GC | Java 内存管理 |
公共路径:框架侧 frameworks/base/services/core/java/com/android/server/am/,系统组件 在 system/memory/lmkd/ 与 system/core/libprocessgroup/,运行时在 art/runtime/。 行号以 r75 检索为准。
进程回收顺序如何产生,见 oom_adj 与进程优先级。