Java OutOfMemoryError : GC overhead limit exceeded Example

This is continuing article of out of memory error explanation. In this post I will provide how to reproduce Java OutOfMemoryError : GC overhead limit exceeded. We will see how to recreate and what are the impact in monitoring tools.

I have used only JVM 1.8 x64 on windows 7 x64/8gb ram/ 2.5Ghz Core i5 laptop.

Tools : 
IDE : Eclipse
Profiling/Monitoring tool :
1. Visual VM
2. Jconsole (optional)
3. Yourkit (optional)

I am using some JVM flags to get detail GC information and monitoring via JMX. Please see this post in step 1 for detail.
I am using these flags here (xmx to limit heap to have quick error)
-verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps
-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=3000
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=localhost
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=D:\OOM
-Xmx100m

Now, for the GC overhead error, it is easily untestable , due to GC is unable to free up the heap with its best efforts. The main cause is, GC is taking 98% of CPU time to cleanup heap where heap is not feeing up more than 2%. In our example, we will see GC overhead multiple time as heap is occupied after certain amount of item entry.

Again, to know about the error, you can visit this original post.

Scenario: 

Very simple scenario, I am adding a string in a map(it is costly, if we use array list, it will take more time) in an infinite loop.

Code : 
public class GCOverheadOOM {
    private static Map aMap = new HashMap();
    public static void createGCOverheadOOM(){
        int i = 0;   
        try{
        while (true) {           
            aMap.put(i, "Shantonu adding String");   
            System.out.println("Total Items "+i++);
        }
        }catch(Throwable e){
            System.err.println("\nError after adding "+ aMap.size()+" items");
            e.printStackTrace();
        }
    }
}

And from main method, call this.
GCOverheadOOM.createGCOverheadOOM();
Note : As this is a GC related error (overhead) , this error fully depends on GC algorithm. This code generates the error in default or parallel GCs. When I used different, I got slightly different one. I have tried following jvm flags to select GC algorithm. Each at a one time
1. -XX:+UseParallelGC -XX:-UseParallelOldGC
2. -UseParNewGC -XX:+UseConcMarkSweepGC
3. -XX:+UseParNewGC -XX:+UseConcMarkSweepGC
4. -XX:+UseG1GC
5. -Xincgc
6. -XX:+UseSerialGC
7. -XX:+UseParallelGC

Oracle has clear indication here.

Error analysis in console  : 

Error Occurred after 1488049 items added. We can see multiple OOM messages for each try by GC.
image

Dump Analysis in Visual VM (created at OOM ): I am using one of errors

Summary : 
 
 

Top contributors : 
image

Visual VM Monitoring : 
GC before ending :
image

Heap :
image


JConsole Monitoring : (overall)
image


Yourkit Monitoring :

CPU usages :
image

Heap : 
image

Non Heap : 
image

Please comment if you have any question.

Thanks.. :)

No comments:

Post a Comment