现象
某天晚上突然收到线上的告警邮件,线上某台机器宕机了,马上上服务器上查看日志,出现了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 Set
和Thread 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
模块服务器某时刻的运行情况:
既然知道了问题的原因,进行接口优化即可解决内存溢出问题。