Thursday, May 11, 2017

Solution of java.lang.OutOfMemoryError: GC overhead limit exceeded

The java.lang.OutOfMemoryError: GC overhead limit exceeded is another type of OutOfMemoryError in Java which comes when JVM spent too much time doing garbage collection without any success.  For example, if almost 98% of CPU for a Java process is busy doing GC and reclaims very less amount of Java heap space around 2%, then JVM throws "java.lang.OutOfMemoryError: GC overhead limit exceeded" error. Though, the definition of 98% CPU time may vary between different Garbage collector and different JVM version.  Unlike java.lang.OutOfMemoryError: Java heap space and java.langOutOfMemory: Permgen space, this is not so frequent and you will rarely encounter this error in your Java application, but this also denotes resource exhaustion.

Btw, if you are thinking that there is only one type of OutOfMemoryError in Java which comes when there is not enough memory in heap to create objects in heap, you are wrong. There are different types of OutOfMemoryError in Java and each denotes different type of resource problems e.g.

java.lang.OutOfMemoryError: Java heap space
This error means not enough heap memory to create new objects.

java.lang.OutOfMemoryError: Permgen space
This error means not enough memory in permanent generation of the heap to load class metadata.

java.lang.OutOfMemoryError: Direct buffer memory
means not enough heap memory to allocate to direct byte buffer.

java.lang.OutOfMemoryError: unable to create new native thread
means your application has exceeded the limit to create threads.

java.lang.OutOfMemoryError: Metaspace
this error is Java 8 equivalent of Permgen error because the Permanent generation has been removed in java 8 and a new Metaspace is introduced.

Now, let's try to find out some of the possible cause of "GC overhead limit exceeded" error in JVM.

Possible cause of GC overhead limit exceeded OutOfMemoryError in Java

If you suddenly start getting java.lang.OutOfMemoryError: GC overhead limit exceeded in your Java application then there are two possibilities either your application have developed a memory leak or you have introduced code changes which demand more memory and tend to store more objects in memory which is preventing Garbage collector to free memory from the heap. To verify this you can do following things

1) find out if you have increased size of your application cache(if any) but not increased -Xmx (max heap size setting) accordingly.

2) find out if you have introduced new cache or caching data structure e.g. Collection classes like HashMap which stores object in memory.

As a general best practice to avoid resource exhaustion you should always use the bounded cache as in the case of unbounded cache you may run out of memory but with the bounded cache, you don't grow without your limit.

Suggestions to fix java.lang.OutOfMemoryError: GC overhead limit exceeded

One of the first thing you can do to solve java.lang.OutOfMemoryError: GC overhead limit exceeded is to find out whether you have a memory leak or not because if you have memory leak changing heap sizes will just delay the occurrence of java.lang.OutOfMemoryError: GC overhead limit exceeded, it won't eliminate it.

But if your application genuinely needs more memory may be because of increased cache size or introduction of new caches then you can do following things to fix java.lang.OutOfMemoryError: GC overhead limit exceeded in Java:

1) Increase the maximum heap size to a number which is suitable for your application e.g. -Xmx=4G. Remember, if you are running on 32-bit JVM you cannot set maximum heap size more than 2G on different operating system e.g. Windows, Linux or Solaris. If your application needs more memory, it's better to switch to a 64-bit Java Virtual Machine. If you try to provide more than 2G to a 32-bit JVM, it will not start and throw invalid heap size error.

2) If you are not using already then try using -XX:+UseConcMarkSweepGC Garbage collector in your Java application. This is one of the best garbage collector available in JVM prior to Java 7. From Java 7 onward you can also use the G1 Garbage collector, which will also become the default garbage collector from Java 9.

If you want to learn more about different types of Garbage collector and how they work, I suggest you read a good book on JVM internals and Java performance tuning e.g. you can choose from definitive guide to Java performance by Scott Oaks or more recent Java performance companion from Charlie hunt, both are great book to learn JVM internals and GC.

Solution of java.lang.OutOfMemoryError: GC overhead limit exceeded

3) Avoid creating too much garbage and reuse temporary object if you can. This should be the last thing you should do because reusing temporary object may create subtle issues. make sure anything you reuse is safe and can be reusable in terms of functionality especially in a concurrent and multi-threading environment.

Don't try to reuse static variables without proper synchronization to avoid any surprise race condition in your Java application.

That's all about how to fix this OutOfMemoryError in your Java application. The " java.lang.OutOfMemoryError: GC overhead limit exceeded" is one of the rare error in Java application, but when it comes it takes some time to go away because finding the actual cause is not very straight forward. You need to a combination of code analysis as well as load analysis for your application. It may also be the time for capacity planning for your application.

Further Learning
Understanding the Java Virtual Machine: Memory Management
Understanding and Solving Java Memory Problems
Java Performance The Definitive Guide

Other Java Troubleshooting Guides you may like to explore
  • How to solve java.sql.BatchUpdateException: String or binary data would be truncated (guide)
  • How to solve java.lang.ClassNotFoundException: com.mysql.jdbc.Driver error? (hint)
  • 5 Reasons of NoClassDefFoundError in Java? (tutorial)
  • How to fix Caused By: java.lang.NoClassDefFoundError: org/apache/log4j/Logger (solution)
  • Cause of "java.lang.SecurityException: Missing required Permissions manifest attribute in main jar" [solution]
  • How to fix "illegal start of expression" compile time error in Java? (tutorial)
  • How to fix "Error: Could not find or load main class" in Eclipse? (guide)
  • How to fis unable to find certification path error in Java SSL? (guide)
  • 10 common reasons of java.lang.NumberFormatException in Java? (tutorial)
  • java.sql.SQLException: No suitable driver found for 'jdbc:mysql://localhost:3306/mysql [Solution]
  • How to solve "variable might not have initialized" compile time error in Java? (answer)
  • How to deal with "No JVM installation found, please install 64-bit JDK" error? (solution)
  • How to fix 'javac' is not recognized as an internal or external command (solution)
  • How to avoid ConcurrentModificationException in Java? (tutorial)
  • How to solve "could not create the Java virtual machine" error in Java? (solution)
  • Common reasons of java.lang.ArrayIndexOutOfBoundsException in Java? (solution)
  • java.lang.ClassNotFoundException : org.Springframework.Web.Context.ContextLoaderListener (solution)
  • java.sql.SQLServerException: The index 58 is out of range - JDBC (solution)
  • Fixing java.lang.unsupportedclassversionerror unsupported major.minor version 50.0 (solution)
  • java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory error (solution)
  • Cause and solution of "class, interface, or enum expected" compiler error in Java? (fix)
  • How to connect to MySQL database in Java? (tutorial)
  • How to solve java.lang.classnotfoundexception oracle.jdbc.driver.oracledriver? (solution)

Thanks for reading this article so far. If you like this tutorial then please share with your friends and colleagues. If you have any question or suggest then please drop a comment. 


sourav suman said...

Good info javin

Javin Paul said...

Glad that you find information useful Saurav. Thanks Javin

Post a Comment