目录

一次-诡异-的-JVM-OOM-事故-原创

目录

一次 诡异 的 JVM OOM 事故 原创

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

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

https://i-blog.csdnimg.cn/img_convert/3bdd57584c0672079fadc07e8f9966cd.png

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

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

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

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

类似的效果见下图:

https://i-blog.csdnimg.cn/img_convert/51ac90745625ef65573bc34fda5833ec.png

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

https://i-blog.csdnimg.cn/img_convert/edb40eccdeb32d915dfecae11f4c2b64.png

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

https://i-blog.csdnimg.cn/img_convert/e18a0a04ab3b48a13ddd589c3493d020.png

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

https://i-blog.csdnimg.cn/img_convert/728e576944bc7284a19c50d299ec4b6b.png

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

https://i-blog.csdnimg.cn/img_convert/964da1877567f7351bbcf05b42b2d49e.png

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

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

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

https://i-blog.csdnimg.cn/img_convert/54c861fdf2d6b681313353b1a88ef802.png

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

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

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

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

https://i-blog.csdnimg.cn/img_convert/60681b597e867c3824c2d1b19ccf8f26.png

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

https://i-blog.csdnimg.cn/img_convert/6b693c18941e6c0f7923934f51e59cfc.png


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

https://i-blog.csdnimg.cn/img_convert/a4d3c146d0bbe89c5aa9d701a954abae.png

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

https://i-blog.csdnimg.cn/img_convert/8a77ccb70a89b957ed4284dd8b14effb.png


我们总结下,解决 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 哦 ,真的出现太多次啦。