记录一次线上OOM的排查过程

2,364 阅读2分钟

现象

某天晚上突然收到线上的告警邮件,线上某台机器宕机了,马上上服务器上查看日志,出现了OOM。

OOM分析

线上的服务器都会配置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/apps/srv/instance/teacher.xiaozao100.com/logs/heapdump.hprof 这个对于排查问题非常有帮助,当发生OOM时会生成堆的内存快照(hprof文件)。 从服务器上下载heapdump.hprof文件

通过jprofiler对dump文件进行分析

打开jprofiler,加载dump文件完成后,信息如下: 只需重点关注Heap Walker下的Current Object SetThread Dump

  • Current Object Set: 确定相关对象(一般就是找大对象),找到对应的线程
  • Thread Dump: 查看对应的线程信息,确定方法的调用者,最终定位到具体的业务操作 由于是内存溢出导致的OOM,因此我们需要关注内存的使用情况,因此根据size进行排序,我们可以先查看下占用内存最大的对象:byte[] PS:
  • incoming references: 显示这个对象被谁引用
  • outgoing references: 显示这个对象引用的其他对象 查看这些对象的引用对象信息: 点击上方的Biggers Objects查看大对象信息: 然后点击Show In Graph查看调用链: 最终,我们可以看到这个对象的调用链信息: 通过上述信息,我们可以知道调用栈所属的线程是XNIO-1 task-292 因此,我们现在可以去Thread Dump中去查看线程的详细信息,并定位到XNIO-1 task-292线程上: 最终定位到teacher模块的pageUnReadComments接口上,该接口逻辑查询的对象较多,主要原因就是把辅导老师带的所有班级学生对象一下子全部查询到内存中去,导致加载到内存太大,GC无法及时处理,在晚上老师们在线给学生纠音的时候,就很容易产生OOM现象。

附上teacher模块服务器某时刻的运行情况:

既然知道了问题的原因,进行接口优化即可解决内存溢出问题。