公司内部一次关于oom告警故障复盘分享报告。总结现象,分析原因,给出了具体解决方案... 最近笔者有点忙,这次OOM事故发生过去两周前,记得笔者那天正带着家人在外地玩,正中午跟
最近笔者有点忙,这次OOM事故发生过去两周前,记得笔者那天正带着家人在外地玩,正中午跟友人吃饭的时候,钉钉连续告警爆表,接着就是钉钉电话(显示广东抬头)一看就知道BBQ了,又一次故障发生了,今天把那次故障复盘一下,做个总结,也给小伙伴分享一下 我是怎么从接到告警开始,怎么一步一步分析故障,然后定位到问题,最后完美解决,成功上线解决问题的。
上述告警内容,由于笔者所在服务是用CMS垃圾回收器,当其GC次数太频繁,达到公司监控平台设置的阈值时,就会通过钉钉通知告知开发者,发送到对应的控制台上。这个异常先从字面意义上来说倒也比较明显,如果老年代里的对象太多,无法提供空间容纳年轻代传递过来的对象的时候,就会触发FULL GC。
这里我们先简单分析一下,对象什么情况下会进入老年代,以及老年代又是在什么情况下会触发FULL GC?只有先知道了原理性东西,你才能带着思路去分析,真实线上场景属于对应哪种情况
首先科普一下对象什么情况下会进入老年代?
1)躲过15次GC之后进入老年代
public class Kafka{ //只要Kafka这个类存在,r这个静态变量就会一直存在 private static ReplicManager r=new ReplicManager(); } 像上面这块代码,成员变量是GCROOT引用,所以一直不会回收不掉;这个对象每次从Eden躲过一次到Survivor区域中,它的年龄就增长1岁,当年龄增加到15岁时候,就会转移到老年代里。 2)动态对象年龄判断 意思是如果Survivor空间中相同年龄的所有对象大小总和大于Survivor空间的一半,年龄大于等于该年龄的对象会直接进入老年代 3)大对象直接进入老年代 4)空间担保策略 在发生MinorGc之前,JVM会检查老年代的最大连续可用空间是否大于新生代所有对象总空间,如果不成立,那么JVM会查看一个参数值查看是否允许担保,如果之前配置了允许,那么会检查老年代最大可用空间是否大于历次晋升到老年代对象的平均大小,如果大于将尝试进行一次Minor GC;如果小于或者参数设置不允许冒险,那么就会进行一次FULL GC。 那老年代又是在什么情况下会触发FULL GC? 1.也是上面第四种情况,就不写了 2.yongGC之后如果满足上述分析的[#首先科普一下对象什么情况下会进入老年代?]其中一种情况,那么进入老年代,但这个时候如果老年代空间不足,就会触发FULLGC 3.如果老年代内存使用率超过92%其实会触发fullgc的 好了先科普一下相关知识点,利于后续的分析做铺垫。下面开始逐步分析具体具体原因,到底是什么大对象充满了老年代内存区域。 首先一碰到特别是线上这种重大事故,第一思路是保留线程,然后快速止血。这也是笔者所在公司对于开发的其中一条军规(估计之前出现过太多的这种事故,形成规范了