You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java线程触发OOM Killer时的日志解读及相关技术疑问

Java线程触发OOM Killer时的日志解读及相关技术疑问

咱们来一步步拆解你遇到的这个Java线程触发OOM Killer的问题,逐一解答你的疑问:

1. OOM Killer消息里的PID来自哪里?

这个PID其实是Linux轻量级进程(LWP,Light Weight Process)的ID,也就是Java线程对应的内核级线程ID。

Java在Linux平台默认采用原生线程模型,每个Java线程都会对应一个内核层面的LWP——你可以把它理解成内核视角下的“线程”。内核在触发OOM Killer时,会把当前发起内存申请操作的那个LWP的ID打出来,而不是整个JVM进程的PID(也就是线程组ID,tgid)。

你可以用ps -L -p <JVM进程PID>命令查看目标JVM进程下的所有LWP,就能找到日志里那个1653163对应的Java线程了。

2. 为什么线程会被单独从JVM进程里拎出来处理?

内核的OOM Killer是针对发起内存分配请求的执行实体来触发告警的,这个实体就是内核级的LWP。当Cassandra的ReadStage-150线程发起内存申请、导致系统内存不足时,内核看到的是这个LWP在申请资源,所以会把它作为OOM的触发者记录下来。

不过你也注意到了,后续的Tasks state日志里依然会列出整个JVM进程的内存情况——这是因为OOM Killer最终决定要杀死哪个实体来释放内存时,评估的是整个线程组(也就是JVM进程)的内存占用,单个LWP的内存数据不足以支撑这个决策。

3. 能不能只中断 culprit 线程而不杀死整个JVM?

理论上,Linux内核确实支持终止单个LWP,但JVM完全不兼容这种操作:

  • JVM的线程模型和内核线程强绑定,强行杀死一个内核LWP会导致JVM内部的线程状态彻底混乱,大概率会引发进程崩溃、资源泄漏,甚至进程hang死无法正常退出。
  • 更关键的是,OOM Killer的设计目标是释放系统级的内存资源,而Java的堆内存是属于整个JVM进程的,不是单个线程私有——就算杀死了单个线程,进程级的内存也没法被有效释放,所以OOM Killer只会把整个线程组(JVM进程)作为目标,不会去尝试杀死单个线程。

补充:日志示例对比

普通进程(snmpd)触发OOM的日志

Jul 18 02:21:26 inm-agg kernel: snmpd invoked oom-killer: gfp_mask=0x100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
Jul 18 02:21:26 inm-agg kernel: CPU: 3 PID: 1190 Comm: snmpd Kdump: loaded Not tainted 5.4.17-2102.201.3.el8uek.x86_64 #2
...
Jul 18 02:21:26 inm-agg kernel: Tasks state (memory values in pages):
Jul 18 02:21:26 inm-agg kernel: [  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name
...
Jul 18 02:21:26 inm-agg kernel: [   1190]     0  1190    78491     1761   217088        0             0 snmpd

这里的PID 1190既是进程ID,也是线程组ID(tgid),所以能在后续任务状态中找到对应条目。

Java线程触发OOM的日志

Jul 16 22:01:45 inm-agg kernel: ReadStage-150 invoked oom-killer: gfp_mask=0x100dca(GFP_HIGHUSER_MOVABLE|__GFP_ZERO), order=0, oom_score_adj=0
Jul 16 22:01:45 inm-agg kernel: CPU: 11 PID: 1653163 Comm: ReadStage-150 Kdump: loaded Not tainted 5.4.17-2102.201.3.el8uek.x86_64 #2
...
Jul 16 22:01:45 inm-agg kernel: Tasks state (memory values in pages):
Jul 16 22:01:45 inm-agg kernel: [  pid  ]   uid  tgid total_vm      rss pgtables_bytes swapents oom_score_adj name
…
Jul 16 22:01:45 inm-agg kernel: [1652432]     0 1652432  7256008  5839621 49709056        0             0 java

这里的PID 1653163是Java线程对应的LWP ID,而任务状态里的1652432是JVM进程的线程组ID(tgid)。

备注:内容来源于stack exchange,提问作者Toparvion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.22 09:18:14