OOM Killer 杀进程可通过 dmesg -T | grep -i "killed process" 确认,无输出需检查权限、日志落盘或 cgroup 限制;关键看上下文中的内存分配失败与 oom_score_adj 权重,并区分真实内存压力与缓存/swap 误判。

直接看 dmesg -T | grep -i "killed process",有输出基本就是 OOM Killer 干的。没输出不等于没发生,可能是日志被刷掉、权限受限或落盘延迟。
第一步:确认是不是 OOM Killer 杀的
Linux 内核在物理内存(含 swap)真正扛不住时,会触发 OOM Killer 主动杀进程。它和 JVM 的 OutOfMemoryError 完全不同——后者是应用层报错,进程通常还在;前者是内核行为,进程已消失,且不会留下 Java 堆栈日志。
- 运行 sudo dmesg -T | grep -i "killed process",看到类似
Killed process 12345 (java) total-vm:6.2GB, anon-rss:4.8GB就坐实了 - 若无输出,先检查权限:sudo sysctl kernel.dmesg_restrict,返回 1 表示非 root 看不到完整日志,临时放开:sudo sysctl kernel.dmesg_restrict=0
- 再查落盘日志:sudo grep -i "out of memory\|killed process" /var/log/messages 或 journalctl -k --since "1 hour ago"
第二步:看“为什么杀”,不能只盯被杀进程
dmesg 那一行只是结果,真正原因藏在前后几秒的上下文里。OOM 是渐进过程,不是瞬间爆发。
- 用 sudo dmesg -T | tail -n 200 拉最近 200 行,重点扫 OOM 时间点前后 5 秒
- 找这些关键线索:
page allocation failure(连一个内存页都分不出)、low memory、free:行(显示各 zone 剩余页数,数值极低说明硬扛不住) - 如果是容器环境,留意
Memory cgroup out of memory—— 这说明不是整机内存爆了,而是某个 cgroup(比如 Docker 容器)超限,得去查/sys/fs/cgroup/memory/xxx/memory.usage_in_bytes
第三步:搞懂谁该先死——oom_score_adj 才是关键
被杀的进程不一定是内存最大的那个。内核用 Badness 算法综合评估,核心依据是 oom_score_adj 值(范围 -1000 到 1000)。
- 查被杀进程当时的权重:cat /proc/12345/oom_score_adj(替换 PID)
- 横向对比所有进程:ps -eo pid,comm,oom_score,oom_score_adj --sort=-oom_score | head -10
-
anon-rss(匿名 RSS)比total-vm更能说明真实压力:它代表进程实际占用的物理内存,不含缓存和文件映射。如果接近机器总内存,大概率就是它拖垮系统
第四步:区分真内存不足和假警报
free 命令里 “available” 列才代表真正可用内存,“buff/cache” 高≠内存不足——那是 Linux 在用空闲内存做磁盘缓存,随时可回收。
- swap 使用不等于出问题,只有
vmstat显示持续的si/so(swap in/out)才危险 - OOM 触发不一定因物理内存耗尽,常见于:Docker 设置了
--memory=2G但 JVM 不知道,疯狂申请堆外内存;或用户级限制ulimit -v被突破 - 虚拟内存(VIRT)大≠真占内存,那是进程地址空间大小,很多页根本没分配物理页


















