一句话定义
OOM Killer(Out-Of-Memory Killer,内存耗尽杀手)是 Linux 内核的保命机制:当物理内存和交换空间都实在不够用时,内核会挑一个进程直接杀掉(发 SIGKILL 信号),腾出内存让整台机器活下来。
它是怎么挑人的
Linux 会尽量把空闲内存拿去做页缓存(page cache)来加速读写,这些内存随时可以回收。真正危险的是那些回收不掉的内存:进程的堆、栈、匿名页。
当内核要分配内存却找不到可用页、也回收不出东西时,就进入 OOM 状态,扫描所有进程算一个 oom_score,分数最高的那个倒霉。评分大致看两件事:一是这个进程实际占了多少物理内存(RSS,Resident Set Size),占得越多分越高;二是它的 oom_score_adj 调整值,范围大约从 -1000 到 1000,数值越小越不容易被杀,调到最低基本等于免疫。
打个比方:大巴超载,司机得请人下车。先看谁占地方最大,再看谁手里的票最不紧急——那个又胖、票又不急的乘客,就是 OOM Killer 的目标。
三个容易混淆的"内存不够"
| 现象 | 谁动手 | 典型线索 |
|---|---|---|
| OOM Killer | Linux 内核 | 进程消失,退出码 137,dmesg 里有 Out of memory: Killed process |
| JVM OOM | JVM 自己 | 抛 java.lang.OutOfMemoryError,进程可能还活着 |
| cgroup OOM | 内核的 cgroup 内存控制器 | 容器被杀,K8s 里显示 OOMKilled 并重启 |
关键区别:JVM 的 OOM 是"堆内部满了"的报错,属于应用层;OOM Killer 是内核从外部开枪,进程没有任何机会做善后,日志、缓存都可能来不及落盘——这正是它"莫名其妙"的原因。
对从业者的实际意义
- 服务半夜消失、容器反复重启、退出码 137(128 + 9,即被 SIGKILL),第一反应就该查 OOM。
- 排查入口:
dmesg -T、journalctl -k、/var/log/messages,搜Out of memory或oom-kill;容器场景再看 cgroup 的memory.events。 - 缓解手段:给容器和进程设合理的内存上限;关键进程调低
oom_score_adj;跑 JVM 时堆上限别贴着容器上限设,要给元空间、线程栈、堆外缓冲留余量;Redis 这类进程开maxmemory并配好淘汰策略。 - 注意:
oom_score的具体计算细节和各参数默认值在不同内核版本、不同发行版间有差异,实际行为以对应内核文档和官方页面为准。
