oom_adj 与进程优先级:应用如何决定生死
oom_adj 与进程优先级:应用如何决定生死
Activity 进入前台后,进程的重要性会随组件状态和依赖关系持续变化。OomAdjuster 在 system_server 中计算 oom_score_adj,lmkd 在出现内存压力时参考该值选择回收对象。 这个数值是排序依据,不是保证进程永远存活的锁。
计算优先级与执行回收是两件事
| 常见误解 | 正确理解 |
|---|---|
| 前台 Activity 的进程永远不被杀 | 内存压力极大时系统仍可能杀进程,只是优先级最高 |
| oom_adj 是 LMK 自己算的 | oom_adj 由 system_server 的 OomAdjuster 计算,lmkd 读取后决定回收 |
优先级不是“生死锁”,而是“先杀谁”的排序。系统给每个进程一个 oom_adj 数值,数值越大越容易被回收;决定权在 LMK,依据来自 AMS。
关键档位
| oom_adj | 档位 | 典型场景 |
|---|---|---|
| 0 | 前台(FOREGROUND_APP_ADJ) | 用户正在交互的 Activity |
| 100 | 可见(VISIBLE_APP_ADJ) | 可见但不交互 |
| 200 | 可感知(PERCEPTIBLE_APP_ADJ) | 播放音乐等服务 |
| 900 | 缓存(CACHED_APP_MIN_ADJ) | 后台任务,可能被回收 |
| 999 | 缓存上限(CACHED_APP_MAX_ADJ) | 最不重要的缓存进程 |
| 1001 | 未知(UNKNOWN_ADJ) | 未参与排序 |
常量定义在 ProcessList.java:197-269(UNKNOWN_ADJ = 1001、CACHED_APP_MAX_ADJ = 999、CACHED_APP_MIN_ADJ = 900、PERCEPTIBLE_APP_ADJ = 200、VISIBLE_APP_ADJ = 100、FOREGROUND_APP_ADJ = 0)。
计算主链
逐步解释:
- ① 触发:Activity 前后台切换、服务绑定、广播等都会触发重算。
- ② AMS 入口:
OomAdjuster.updateOomAdjLocked()(OomAdjuster.java:567 / 607)。 - ③ 计算:
computeOomAdjLSP()(OomAdjuster.java:1750)按组件状态算出 adj。 - ④ 落地:结果写入 ProcessRecord,并通过机制同步给内核侧。
- ⑤ 回收:lmkd 依据 oom_score_adj 在内存压力下按序杀进程。
ProcessRecord 是什么
ProcessRecord(ProcessRecord.java:81)是 system_server 对应用进程的记录:进程名、uid、pid、adj、已连接的组件。AMS 的进程表以它为基本单位,所有组件(Activity/Service/广播)的归属都指向它。
源码证据
阅读目标:确认 oom_adj 由 system_server 计算。
正文指针:ProcessList.java:201;OomAdjuster.java:1750;AMS.java:2658。
// ProcessList.java:201
public static final int CACHED_APP_MAX_ADJ = 999;// OomAdjuster.java:1750
protected boolean computeOomAdjLSP(ProcessRecord app, int cachedAdj, ...) {这段代码证明: 档位是 ProcessList 的常量,计算在 OomAdjuster;AMS 构造时也会立刻做一次全量 updateOomAdjLocked(OOM_ADJ_REASON_SYSTEM_INIT)(AMS.java:2658)。
LMK 的边界
lmkd 是独立 native 进程,读取系统下发的 oom_score_adj 并在内存压力下回收进程。它不参与“这个进程应该排第几”的计算,只执行“按序回收”。设备厂商的 LMK 策略可以调整,因此同一 Android 版本在不同设备上的回收行为可能不同。
源码入口
源码基准:android-14.0.0_r75。
以下文件默认位于 frameworks/base/,表中省略该前缀:
| 文件 | 关键位置 | 作用 |
|---|---|---|
services/core/java/com/android/server/am/ProcessList.java | 197 行 UNKNOWN_ADJ = 1001;201 行 CACHED_APP_MAX_ADJ = 999;202 行 CACHED_APP_MIN_ADJ = 900;255 行 PERCEPTIBLE_APP_ADJ = 200;259 行 VISIBLE_APP_ADJ = 100;269 行 FOREGROUND_APP_ADJ = 0 | 优先级档位 |
services/core/java/com/android/server/am/OomAdjuster.java | 180 行 class OomAdjuster;567 / 607 行 updateOomAdjLocked(...);1750 行 computeOomAdjLSP(...) | adj 计算 |
services/core/java/com/android/server/am/ProcessRecord.java | 81 行 class ProcessRecord | 进程记录 |
services/core/java/com/android/server/am/ActivityManagerService.java | 2658 行 updateOomAdjLocked(OOM_ADJ_REASON_SYSTEM_INIT) | 初始全量计算 |