JVM运行报错:GC overhead limit exceeded
今天在折腾OOM和java的4种引用类型的时候,在运行过程中JVM报了一个错误:
java.lang.OutOfMemoryError: GC overhead limit exceeded
The concurrent collector will throw an OutOfMemoryError if too much time is being spent in garbage collection: if more than 98% of the total time is spent in garbage collection and less than 2% of the heap is recovered, an OutOfMemoryError
will be thrown. This feature is designed to prevent applications from running for an extended period of time while making little or no progress because the heap is too small. If necessary, this feature can be disabled by adding the option-XX:-UseGCOverheadLimit
to the command line.
我使用的是JDK1.6.0_37和JDK_1.7.0_60版本,这2个版本中JVM默认启动的时候-XX:+UseGCOverheadLimit,即启用了该特性。这其实是JVM的一种推断,如果垃圾回收耗费了98%的时间,但是回收的内存还不到2%,那么JVM会认为即将发生OOM,让程序提前结束。当然我们可以使用-XX:-UseGCOverheadLimit,关掉这个特性。
不太明白为什么JDK要提供这么个参数。当我们遇到这个错误只能说明:要么是内存空间不足,要么是存在内存泄露。这个时候对我们有意义的,其实就是heap dump,我们可以分析堆内存的情况,从而诊断出是否代码存在问题。
我们知道如果在启动JVM的时候设置了如下的参数,那么JVM崩溃的时候会打印出heap dump。
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=C:/
个人感觉,如果真的发生了"GC overhead limit exceeded"错误,那么其实离实际的OOM已经不远了,所以让JVM做个预测提前结束,感觉意义不大。