Few errors are deadlier than java.lang.OutOfMemory errors. When this happens, you application will run into a very unpredictable state, often hanging up and not processing new requests, coughing up ugly stack traces into users browsers etc. The most popular (and effective in the short run) fix for OutOfMemory error is simply restarting the Application or Application Server.
While running out of java Heap is the most common OutOfMemory error, there are indeed several types of OutOfMemory that can occur. In this post, I will show you these various types of OutOfMemory errors and what they mean.
java.lang.OutOfMemoryError: Java heap space
The most popular one. This is when JVM goes belly up and unable to allocate memory in Heap . Your application might appear hung up and extremely slow to respond to user requests.
For example, let’s say your Java application has 2GB of memory maximum (through -Xmx flag). When the entire 2GB is used up and GC is unable to reclaim any memory, the next memory allocation request for an object will fail with java.lang.OutOfMemory Error.
What causes java.lang.OutOfMemoryError: Java heap space ?
The common reason is Memory Leak (assuming, and this is a big assuming, you have already allocated enough max heap via -Xmx). Your application is using up memory but never releasing them (i.e garbage collection is unable to reclaim memory). If you are to plot a graph of Heap Utilization, you will see an upward slowing staircase (where as a healthy application should show a ‘saw tooth’ pattern). When you recycle the Application Server, you get a fresh quota of memory and the cycle starts again. If you have a memory leak, depending on the severity of the leak, the application might last for few days (or few hours) after every restart.
Another reason for java.lang.OutOfMemory Error:Java heap space is faulty code that abruptly starts consuming large chunks of memory – for example, code going into an infinite loop, or trying to load millions of records in to memory without pagniation.
A less common reason that I know of is excessive use of ‘finalizers’. When a class has a finalize method, objects of that type do NOT get reclaimed through normal GC. They go into a special finalization queue to be handled at later time.
What can you do about java.lang.OutOfMemoryError: Java heap space?
You need to get to the bottom of the error. This is easier said than done. If you are using third-party libraries and APIs, there is also a chance that the memory leak is occurring in the API/library. My approach is to take a heap dump and analyze it with Eclipse Memory Analyzer. You can also try jcmd test GC.class_histogram
Note: Metaspace is introduced from Java 8. In pre-java8 world, it would be PermGen.
Metaspace is where JVM stores ‘class meta data’ and ‘interned strings’. For an application using tons of third-party libraries, I’ve seen utilization of this space go up. The space is limited by MaxMetaSpaceSize command line parameter.
What causes java.lang.OutOfMemoryError: Metaspace ?
Generally due to third-party libraries that use native code. Note that running out of Meta Space does NOT indicate a java memory leak in the application (i.e) it is most probably NOT a code issue. Your focus should be on the various libraries that your application uses.
What can you do about java.lang.OutOfMemoryError: Metaspace ?
Increase MaxMetaSpaceSize as first line of defense. You do this by adding the java command line parameter -XX:MaxMetaspaceSize=<size>. If you have to increase beyond 1 GB (for most applications), I would start to speculate a native memory issue originating from your third party libraries.
java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
This is definitely a native memory issue. JVM throws this when an allocation request in native memory fails. You can double-check this by making sure you have NOT run out of Java heap (by checking verbose GC logs or by monitoring the Heap usage).
What causes java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space ?
Leak in native memory is the primary suspect. And that can happen for any number of reasons. For example, if your application opens numerous network sockets erroneously, or when a third-party library opens tons of files erroneously.
What can you do about java.lang.OutOfMemoryError: request size bytes for reason. Out of swap space?
For starters, take a look at the fatal error log file produced by JVM. This file is usually named hs_err_pid.log. It is found in the working directory of the JVM Process (or via -XX:ErrorFile=<file>). This file usually contains good information about the native calls. You can also use OS tools for debugging (such as gdb,dtrace,strace,lstack,pstack etc). I have to be honest, dealing with native memory issues is no fun. But with persistence, you will be able to uncover the culprit.
java.lang.OutOfMemoryError: GC Overhead limit exceeded
This is an interesting one. As the message indicates, GC is creating considerable overhead. This means that application is spending most of the time in GC rather than doing application work. Users will usually see hung-up browser sessions and poor response times.
What causes java.lang.OutOfMemoryError: GC Overhead limit exceeded ?
Most likely reason is heap is filled up with live objects and the new memory allocation request rate is too much for the JVM to handle. As per Oracle’s documentation, if the Java process is spending more than approximately 98% of its time doing garbage collection and if it is recovering less than 2% of the heap and has been doing so far the last 5 (compile time constant) consecutive garbage collections, then a java.lang.OutOfMemoryError is thrown.
What you can do about java.lang.OutOfMemoryError: GC Overhead limit exceeded ?
Try increasing the Heap size (-Xmx). If that does not fix it, you may have to find the root cause by taking a heap dump and reviewing the objects in the heap. Note that you can turn off this exception with -XX:-UseGCOverheadLimit java command line parameter.
java.lang.OutOfMemoryError: Requested array size exceeds VM limit
This is also an interesting one. It occurs when JVM cannot allocate memory space for an array (or a collection object)
What causes java.lang.OutOfMemoryError: Requested array size exceeds VM limit ?
Possibly a code issue where application is trying to erroneously create a huge array. Other possibility is your heap size is erroneously too small (-Xmx)
What you can do about java.lang.OutOfMemoryError: Requested array size exceeds VM limit ?
Check your max heap size to make sure you have adequate memory allocated. Check to make sure your application is not trying to create a huge array.
There you have it folks. Not all ‘OutOfMemory’ errors are made equal :-). Review the associated detail message that generally indicates where the problem is. Most common OutOfMemory error occurs in Java Heap. You can use verbose GC logs and heap dump to find the root cause. Native memory leak can be difficult to diagnose and you may have to summon OS tools to troubleshoot further.
PS: There are a couple of more OutOfMemory errors that I rarely (as in never) see in the field. Here they are:
java.lang.OutOfMemoryError: Compressed class space
java.lang.OutOfMemoryError: reason stack_trace_with_native_method
If you have encountered (and hopefully conquered) the above errors, please chime in by commenting below.