记一次OOM排查

周末的时候我们有一个服务集群两台服务器oom了,由于这个集群历史上经常会出问题,所以当时直接重启,然后观察了一下服务正常之后就继续做饭去了……

周一上午来到公司,发现集群的另外两台服务器又oom了,具体报错为Java.lang.OutOfMemeoryError:GC overhead limit exceeded意思就是我已经GC了,但是能回收的内存太少了(一般是不足百分之二),我这小暴脾气立刻就上来了,这怎么能忍,于是立刻联系运维同学帮忙搞下堆dump,这里还有个小插曲,我在联系运维的时候同事重启了我给运维同学发的服务器,还好还有一台还挂着,于是紧急通知同事停手(沟通的重要性)。等待运维大佬处理约莫半小时后才磨磨唧唧把文件搞了出来,接近4个G,然后又要把文件从服务器搞下来,又是半个小时。。。。

开整,首先装入堆dump,查看类对象

在这里插入图片描述

好家伙,简直是不用查他自己就蹦出来了,直接通过名称找到对象
在这里插入图片描述
在这里插入图片描述
可以看出这个对象管理的还蛮严格,只有这一个地方能new,然后会添加到一个list里面,既然源头找到了 那再看看消费情况
在这里插入图片描述
在这里插入图片描述
会有一条线程一直来处理这个,那这个时候就大致有两个思路:
1:出于某种原因,gc出了问题,并不能将消费完的WritingTask 和arrayList回收掉 但是正常来讲,线程只停顿了10ms,从实际业务场景来看,arraylist并不会比WritingTask少特别多,但是我们堆信息里面并没有特别多的arrayList对象,所以这个排除
2:WritingTask一直在同一个list里面不停的堆积,从未被消费过,这里我查了下消费的代码,由于这个是配置的控制台日志,所以最终会去调用system.out。那如果不消费的话我能想到的有两种情况,一个是线程阻塞了,一个是线程根本就没有起
至此,这个堆dump差不多就没啥用了,既然有了思路,自然是要验证一下,本地启动服务,然后查看线程
在这里插入图片描述
果然,线程根本就没启动,只进不出难怪一直内存溢出,到这里基本上就搞得差不多了,剩下的都要根据具体的系统去分析了,我这里是因为……唉,算了,骚断腰的操作,不提也罢,前人挖坑后人躺。
最后总结一下大致的排查流程:
1:凡事先不要慌
2:先确认一下是什么类型的oom
3:搞到堆dump或者线程dump(一般堆溢出就堆dump)
4:分析类实例,查找异常实例(一般都是异常的多)
5:找到这个实例的创建节点和废弃节点(失去引用)
6:分析为何会创建如此多的对象还一直都有引用
7:定制解决方案

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值