This short article will provide you with a description of this new JVM 1.6 HotSpot OutOfMemoryError error message and how you should attack this problem until its resolution.
You can also refer to this post for a real case study on a Java Heap problem (OutOfMemoryError: GC overhead limit exceeded) affecting a JBoss production system.
Please also feel free to post any comment or question if you need help with your problem.
java.lang.OutOfMemoryError: GC overhead limit exceeded – what is it?
Everyone involved in Java EE production support is familiar with OutOfMemoryError problems since they are one of the most common problem type you can face. However, if your environment recently upgraded to Java HotSpot 1.6 VM, you may have observed this error message in the logs: java.lang.OutOfMemoryError: GC overhead limit exceeded.
GC overhead limit exceeded is a new policy that was added by default for the Java HotSpot VM 1.6 only. It basically allows the VM to detect potential OutOfMemoryError conditions earlier and before it runs out of Java Heap space; allowing the JVM to abort the current Thread(s) processing with this OOM error.
The policy criterias are based on the elapsed time and frequency of your VM GC collections e.g. GC elapsed time too high, too many Full GC iterations or too much time spent in GC can trigger this error.
The official Sun statement is a par below:
The parallel / 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.
Is it useful for Java EE production systems?
I have found on most of my problem cases that this new policy is useful at some level since it is preventing a full JVM hang and allowing you to take some actions such as data collection, JVM Heap Dump, JVM Thread Dump etc. before the whole JVM becomes unresponsive.
But don’t expect this new feature to fix your Java Heap problem, it is meant to prevent a full JVM hang and to abort some big memory allocation etc. you must still perform your own analysis and due diligence.
Is there any scenario where it can cause more harm than good?
Yes, Java applications dealing with large memory allocations / chunks could see much more frequent OOM due to GC overhead limit exceeded. Some applications dealing with a long GC elapsed time but healthy overall memory usage could also be affected.
In the above scenarios, you may want to consider turning OFF this policy and see if it’s helping your environment stability.
java.lang.OutOfMemoryError: GC overhead limit exceeded – can I disable it?
Yes, you can disable this default policy by simply adding this parameter at your JVM start-up:
Please keep in mind that this error is very likely to be a symptom of a JVM Heap / tuning problem so my recommendation to you is always to focus on the root cause as opposed to the symptom.
java.lang.OutOfMemoryError: GC overhead limit exceeded – how can I fix it?
You should not worry too much about the GC overhead limit error itself since it’s very likely just a symptom / hint. What you must focus on is on your potential Java Heap problem(s) such as Java Heap leak, improper Java Heap tuning etc. Find below a list of high level steps to troubleshoot further:
· If not done already, enabled verbose GC >> -verbose:gc
· Analyze the verbose GC output and determine the memory footprint of the Java Heap; including the ratio of Young Gen vs. Old Gen.. Having an old gen footprint too high will lead to too many frequent Full GC and ultimately to the OOM : GC overhead limit exceeded
· Analyze the verbose GC output or use a tool like JConsole to determine if your Java Heap is leaking over time. This can be observed via monitoring of the HotSpot old gen space.
· Look at your young Gen requirement as well, if you application generates a lot of short live objects then your Java Heap space must be big enough in order for the VM to allocate a bigger Young Gen space
· If facing a Java Heap leak and / or if you have concern on your Old Gen footprint then add the following parameter to your start-up JVM arguments: -XX:+HeapDumpOnOutOfMemoryError . This will generate a Heap Dump (hprof format) on OOM event that you can analyze using a tool like Memory Analyzer or JHat.