java.lang.OutOfMemoryError: GC overhead limit exceeded原因及解决方法
问题复现:11-23日生产推送数据时,发生该错误,没有其他操作.
解释STW:
vm在执行垃圾回收线程时,其他线程都会被迫停止,只有垃圾收集线程执行完毕,其他线程才会恢复,这期间会有很少的等待时间,这个过程就是stw。
错误含义:
该错误表示cpu在98%(默认值)的时间内都在处理jvm的垃圾收集(STW),且堆中回收到的内存仍是低于2%,这时系统就会报GC overhead limit exceeded。
错误分析:
两种情况导致这种情况
一:服务器内存过小,不能支撑jvm的运行
二:为堆设置的内存过小(-Xmx ,-Xms)
找出问题:
生产一台服务器,部署了8个java微服务应用,也就是可以看成8个jvm在运行,虽然相互之间不打扰,但是内存在平时就会占用过高,很容易就会OOM,-Xms512m -Xmx512m -Xss1024k -XX:ParallelGCThreads=2 -Djava.compiler=NONE,这个是jvm配置参数,解释下各个参数意思,-Xmx512m:堆最大使用内存为512M,-Xms512m:堆最小使用内存为512M,-Xss1024k:单个线程的栈空间为1M(虚拟机栈与本地方法栈共用),-XX:ParallelGCThreads=2:垃圾收集线程最大数为2,即使用2个并行线程进行垃圾回收, -Djava.compiler=NONE:这个是禁用JIT(即时编译器)编译器的命令,默认是启动的(禁用JIT,就会使用转译器,转译器更适合debug使用,JIT运行程序会更快)。
解决方案:
①让该错误消失:-XX:-UseGCOverheadLimit,jvm增加这个参数会让GC overhead limit exceeded该错误消失,只会出现Java heap space。这不是根本解决办法,只是不报该错误。因为GC overhead limit exceeded相当于Java heap space他的预警。
②优化堆参数配置:增加-Xmx 与-Xms 两个参数大小。
③增加服务器内存:如果不是内存泄漏可以使用这种情况,内存泄漏只增加内存,只是治标不治本。