Introduction
OutOfMemoryError is an exception handled by the JVM and usually means the application is not properly sized or it is taking more than what its memory intended size. It can be direct development team issues, sometimes an actual leak (in native or heap) or an issue on the deployment with an undersized heap. Regardless of how it came up, OOME should be addressed.
Automatic generation For automatically generating heap dumps on JDK 11, in case of OOME, is pretty straight forward, following the previous versions – just add the flag when calling java – and when the OOME happens the heap dump will be automatically generated:
-XX:+HeapDumpOnOutOfMemoryError
This is interesting given some container have ExitOnOutOfMemoryerror flag, so on OOME event, the JVM will exist and most of the times we will see the pod terminating code153 or code 0 – given only one container per pod so the container just exists.
Manual generation: given jcmd avaliable one can generate a heap dump or VM.info as well – both very useful for heap and native investigations respectively.
Generating
$ java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path/JDK11/java_application
Generated file
The generated file will be java_pid[number].hprof – hprof is a type of file. For its analysis I most of the times use Eclipse MTA – pretty straightforward opening the file. I think I have blog posts about querying the data from the heap and completing the analysis.
Testing
For testing, I used the scripts from here – but be aware that some tests have perm generation, which is deprecated on JDK 8 forward, now it is metaspace, so native memory.
Actually, the second example is pretty straight forward – Error 2 – GC Overhead limit exceeded
// Java program to illustrate
// GC Overhead limit exceeded
import java.util.*;
public class Wrapper {
public static void main(String args[]) throws Exception
{
Map m = new HashMap();
m = System.getProperties();
Random r = new Random();
while (true) {
m.put(r.nextInt(), "randomValue");
}
}
}
But I didn’t run with his suggestion and instead, run it without it. Just to see how long it would take. I regretted because the file is huge, given the hprof was a photochart of the entire jvm heap memory at the time is generated.