一次非常典型的 JVM OOM 事故 (要注意 where 1 = 1 哦)

当面对 JVM OOM 时,你会紧张吗 ? 会不会手足无措 ?

这篇文章,分享前段时间帮一位同学梳理面对 JVM OOM 事故时的解题思路。

首先从对话中,我们可以看到内存溢出呈现两种情况:

  • 运行一段时间之后,CPU 飙高 ;
  • 服务假死,表现出来日志没有任何输出。

我的第一反应是:非常明显的 JVM 内存溢出表现 ,不过不知道是爆炸性的内存增长,还是缓慢的内存增长。

于是,我回复:可以每隔一段时间 观察 top -p Pid (进程号) 看看应用的内存占用情况。

类似的效果见下图:

接下来,我让他通过 jstat -gcutil pid 1000 看看 gc 的频率 。

从图中,新生代 E 区和老年代基本都满了 ,我基本可以确定是海量大对象产生导致 JVM OOM 了。

定时任务这四个字如电光火石般在我眼前闪过,基本八九不离十了。

接下来,他发了张那段时间的监控图:

哇,这张图太有画面感了,我都能感觉到 GC 线程在四处灭火,但依然无法释放内存的彷徨。

最后,我有点担心,是不是 JVM 内存分配小了才导致 OOM 了,同学的回复是 : 12 G 。

我觉得内存大小还可以 ,一般情况下通过 jmap -heap pid 来查看,示例图如下:

分析到这里,基本上我得到了如下的结论:

1、要查看代码中是否有一次性查询海量对象的操作 ;

2、或者有什么公共的对象一直在使用,而忘记了释放;

3、12 G 对一般的小应用来讲是绰绰有余的,而且他们的应用非高并发场景,是内网系统。

最后,我建议观察在日志停的那个时刻到底做了哪些事情,那才是真正的案发现场


那到底是什么原因导致 JVM OOM 呢 ? 和我预期的基本一模一样:

SQL 语句类似下图,查询条件没有拼接好,导致全表扫描。


我们总结下,解决 JVM 内存溢出问题的流程:

1、分析事故现场(CPU、内存、日志);

2、通过 top -p Pid (进程号)分析进程资源占用,判断是爆炸性的内存增长,还是缓慢的内存增长。

3、 jstat -gcutil pid 1000 看看 gc 的频率 ,可以分析是否有大对象产生以及 查看 GC 频率。

4、 jmap -heap pid 分析真实的 JVM 内存占用 ,确认是否真的内存分配得太小了。

5、 事故发生当时到底做了什么,有没有出现类似于内存或者 CPU 占用呈现脉冲飙高样子。

6、 若有飙高的场景,分析彼时彼刻到底有哪些操作。

7、 若是缓慢增长,则考虑使用 MAT 结合排除法分析内存占用。

上面的流程是我解决过内存溢出的套路,虽然很糙,但很实用,比如曾经帮助艺龙支付团队解决过订单查询内存溢出问题、西南某航空公司用户中心内存溢出问题等等。

最后,我想说:一定要注意 where 1 = 1 哦 ,真的出现太多次啦。

相关推荐
苏三说技术2 小时前
LangChain4j 和 LangGraph4j,哪个更好?
后端
ServBay3 小时前
7 个AI开发中真正用得上的 MCP Server,配合Claude Code食用效果更佳
后端·claude·mcp
妙码生花3 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(十五):优化细节、网络请求封装
前端·后端·ai编程
用户6757049885024 小时前
Go 语言里判断字符串为空,90% 的人都写错了!
后端·go
用户6757049885024 小时前
Go 进阶必修:90% 的人都没用对的“表驱动法”
后端·go
小兔崽子去哪了4 小时前
Java 生成二维码解决方案
java·后端
苍何4 小时前
懂事的 Agent 已经开始自己看屏幕干活了,效率起飞!
后端
掘金码甲哥4 小时前
1分钟买不了吃亏系列: nginx动态域名解析
后端
神奇小汤圆5 小时前
2026大厂Java岗面试记录:八股+场景+项目+AI,一文讲透快速上岸路径(含答案)
后端