Sunday, May 7, 2023

How to Fix java.lang.OutOfMemoryError: GC overhead limit exceeded Error in JVM [Solution]

Hello guys, if you are getting  java.lang.OutOfMemoryError: GC overhead limit exceeded Error in your Java application and wondering how to solve this then read on. As suggested by Java virtual machine, java.lang.OutOfMemoryError: GC overhead limit exceeded error comes when JVM breached GG overhead limit; which means your application is spending too much of garbage collection time without freeing any meaningful space. Currently Java's HotSpot virtual machine throws "java.lang.OutOfMemoryError: GC overhead limit exceeded" when 98% of total time is spent in the garbage collection and less than 2% of heap memory is recovered. Now let's find out what are symptoms of this error? Before this out of memory error comes you will see very slow or hung Java application with high CPU usage, because your application is only doing GC. 

To give you more background about this error, let's start with how Garbage collection works in Java. Unlike C and C++ programming, where programmer is responsible for allocating and freeing up memory, In Java platform, Java virtual machine allocates memory to new objects and garbage collector, a process inside JVM, reclaims memory from dead object. 

Every Java application starts with certain heap memory and grows until a limit, but when your application is close to reach to maximum heap size, or crossed a predefined threshold, GC kicks in and frees up some memory which can be allocated to new objects. 

Due to long running time or because of excessive user request if all heap memory is exhausted and GC is not able to free any memory, despite its best effort than JVM throws "java.lang.OutOfMemoryError: GC overhead limit exceeded" error. It's unlikely to recover from this error and only immediate solution is to restart your application.

 By the way, It's not easy to deal with this errors in production until you have good knowledge of Java virtual machine, Garbage collectors, GC tuning parameters and performance monitoring tools.

I suggest every senior Java developer to at-least read one book in JVM performance monitoring and one the best book I feel is Java Performance The Definitive Guide by Scott Oaks. It is not latest, covers up-to JDK 7 and brief overview of Java 8, and full with tools, process and approach to deal with JVM performance and issues like out-of-memory error and memory leaks.




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

As I said, main cause of java.lang.OutOfMemoryError: GC overhead limit exceeded error is that GC spent 98% of time to free up just 2% of memory and this happens across multiple GC cycles. This error can be thrown from the Serial, Parallel or Concurrent garbage collectors. It often means that the Xmx (maximum memory) value is too high, however it can also be because it is too low.

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 in your application's list of virtual machine arguments. 

This kind of OutOfMemoryError can also be caused if huge number of user request exhausted available resources in the JVM. When this occurs, performance will degrade aggressively. This will eventually require a restart or the application may recover.  By the way, if you are facing out of memory error related to permgen space you can also take a look at my previous solution here.

Fixing java.lang.OutOfMemoryError: GC overhead limit exceeded error in JVM



Solution of GC Overhead Limit Exceeded Error in Java

Immediate solution is to restart your Java application so that it can start serving the request. A more strategic solution is to fine tune the maximum heap size -Xmx parameter so that enough memory is available even during maximum load. If you see this error without any significant increase in your program's input like number of orders or number of user request, then it could be due to memory leak also. 

If your application is unintentionally keeping reference of objects, which is no longer needed like a served user request then you will eventually run out of memory no matter how much memory you allocate to your application. 

It's better to monitor your application's CPU and memory usage over time, if you see toothpick pattern, where memory usage is keep on increasing with time then there is definitely a memory leak exists. Other preventive steps which you take in case of java.lang.OutOfMemoryError: Java Heap space is also valid here like tuning memory size, splitting application load across multiple JVM etc.




GC Overhead Limit Exceeded Error in Real life

Some of the places where you will often see "java.lang.OutOfMemoryError GC overhead limit exceeded" is Java IDEs like Eclipse, Netbans or Android Studio and popular web servers like Tomcat, WebLogic and JBoss. 

If you are getting java.lang.OutOfMemoryError: GC overhead limit exceeded in Tomcat or WebLogic then try to split your load into multiple instances of application, this is called load balancing and its a proven strategy to counter excessive load. 

I have seen issues where Tomcat crashing by "java.lang.OutOfMemoryError: GC overhead limit exceeded" because of large number of application sitting on same instance and one of them is hit by large number of users. 

It's always better to deploy each web application into their own tomcat instance, because it not only reduce memory overhead but also prevent other application from crashing due to one application hit by large requests.  To avoid "java.lang.OutOfMemoryError: GC overhead limit exceeded" in Eclipse, close open process, unused files etc.



Important points to Remember

1. One of the early symptom of this error is system running slow or hung on a request. 

2. Oracle's HotSpot JVM throws "java.lang.OutOfMemoryError: GC overhead limit exceeded" to indicate that 98% of time is spent just to free up 2% of space.

3. JVM allows you to disable this message by using -XX:-UseGCOverheadLimit JVM argument, note the "-" sign which is used to disable, but this would just wrap this error into java.lang.OutOfMemorryError:Java heap space.

4. This error is also an indication of that system resources are drained by excessive number of user requests or messages.


5. All types of garbage collector like Serial, Parallel and Concurrent can throw this error.
If heap space memory is too high, you might consider lowering it, conversely If heap size is too low, consider increasing it.

6. Profile your application to see if there is any memory leak which is keeping objects alive


That's all about how to deal with  java.lang.OutOfMemoryError: GC overhead limit exceeded error in Java virtual machine. This error comes when GC is not able to free any memory despite of its best efforts and virtual machine cannot full-fill incoming memory requests. Early symptoms of this error is slow and hung application. 

Once you hit, there is no other way to solve this error but to restart your application. Only strategic way to deal with java.lang.OutOfMemoryError: GC overhead limit exceeded error is to reconfigure your virtual machine memory and utilize load balancing technique to distribute load. It's also good to check for any memory leak by observing memory profile of application over a week or so.

No comments :

Post a Comment