vlambda博客
学习文章列表

一次JVM OOM问题排查

项目出现java.lang.OutOfMemoryError:GC overhead limit exceeded


用jmap查看jvm 堆的情况(如下),发现年轻代的Eden Sapce和老年代的空间接近饱和,初步分析是由于老年代的空间无法回收,进而导致年轻代的空间积压,在”最后一根稻草“的作用下,发生out of memory error。

sudo jmap -heap pid(java进程id)


一次JVM OOM问题排查


使用jmap dump出jvm堆信息,但导出jvm堆信息时失败,提示以下异常,并且导致tomcat重启了

Caused by: sun.jvm.hotspot.utilities.AssertionFailure: can not get class data for sun/net/ExtendedOptionsImpl$$Lambda$10x00000007c01fe828


这是JDK的bug,详情见https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8073605。由于线上jdk版本问题,导致无法dump线上的JVM堆。既然代码有问题,那么在本地跑一下不也能定位问题吗?


将代码在本地跑起来,观察JVM 堆的情况,果不其然,在本地运行时,JVM老年代被使用的空间随着时间越来越多,此时将JVM 堆导出来。

jmap -dump:format=b,file=heap.bin pid(java进程id)


使用Eclipse Memory Analyzer打开heap.bin,对JVM堆进行分析。

找到内存泄漏的地方了,接下来就好办了。最后发现是队列中,出列的数量相对少于进列的数量,随着时间推移,导致队列中积压了大量数据,最终引发了OOM。