现象:

由于需要将mysql表中的过期数据在凌晨定时读取出过滤后转入到MongoDB,一个转换SQL达到百行,而且有几十个,集中运行后程序反馈异常:

Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded

Heap内存:1.5G,程序在Docker容器限制使用内存2G。

监控到内存GC变化:

一次OutOfMemoryError: GC overhead limit exceeded-LMLPHP

Heap内存占用骤升至1.2G,然后不停的进行FullGC,而且间隔非常短,从下图中可以看出PermGen稳定,这也表明读取的数据由于太大是直接进入了老年代内存。

一次OutOfMemoryError: GC overhead limit exceeded-LMLPHP

这时候CPU也彪升接近100%

一次OutOfMemoryError: GC overhead limit exceeded-LMLPHP

请求访问时长也加长,异常反馈。

一次OutOfMemoryError: GC overhead limit exceeded-LMLPHP

java.lang.OutOfMemoryError: GC overhead limit exceeded 这种情况发生的原因是程序基本上耗尽了所有的可用内存, GC 也清理不了。

更准确的说法应该是:执行垃圾收集的时间比例太大,有效的运算量太小。默认情况下,如果GC花费的时间超过 98%,并且GC 回收的内存少于 2%,JVM 就会抛出这个错误。

网友的解决建议:

有的人在解决 “java.lang.OutOfMemoryError: GC overhead limit exceeded” 错误时,配置了下面的启动参数:

// 不推荐
10-15 17:51