一次非常典型的 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 哦 ,真的出现太多次啦。

相关推荐
Re2752 小时前
揭秘索引的 “快”:从翻书到 B+ 树的效率革命
后端
David爱编程3 小时前
Java 三目运算符完全指南:写法、坑点与最佳实践
java·后端
学习编程的小羊4 小时前
Spring Boot 全局异常处理与日志监控实战
java·spring boot·后端
Moonbit5 小时前
MoonBit 作者寄语 2025 级清华深圳新生
前端·后端·程序员
前端的阶梯5 小时前
开发一个支持支付功能的微信小程序的注意事项,含泪送上
前端·后端·全栈
咕噜分发企业签名APP加固彭于晏5 小时前
腾讯元器的优点是什么
前端·后端
AAA修煤气灶刘哥6 小时前
Swagger 用着糟心?试试 Knife4j,后端开发狂喜
后端·面试
bobz9656 小时前
MCP on windows
后端
泡海椒6 小时前
jquickexcel 全功能指南:从数据导入到精美导出的完整流程
后端
iOS开发上架哦6 小时前
移动端网页调试实战,键盘弹出与视口错位问题的定位与优化
后端