When Your JVM Crashes With OutOfMemoryError

Getting OutOfMemoryError: java heap space is probably one of the most annoying thing to happen to your application server. As application gets more complex and your boss keep pushing you to implement new functionality faster, it’s easy to forget about heap consumption efficiency

Fortunately there are few things you can do to analyze the root cause, and attempt to solve the issue. I stumbled upon a little useful JVM option -XX:+HeapDumpOnOutOfMemoryError when digging Oracle Hotspot VM documentation. What this option will do is to generate a heap dump file something like java_pid1234.hprof right before the java process terminates. You can then load this file into an analysis tool like jvisualvm to have a look at what’s going on.

Let’s give this a go!

Let’s write a tiny little program that leaks a huge amount of memory (let’s hope none of your programmer colleague does anything like this)

[sourcecode language="java"]
public class LittleLeaker {

/**
* A little piece of program that leaks a lot of memory
*/
public static void main(String[] args) {
ArrayList array = new ArrayList();

while (true) {
array.add("Let’s leak some memory here");
}
}

}
[/sourcecode]

Compile it, and run the code with following command

[sourcecode language="text"]
java -XX:-HeapDumpOnOutOfMemoryError LittleLeaker
[/sourcecode]

You shouldn’t have to wait too long until your VM gave up and throw OutOfMemoryError. When it does, notice the hprof file that got created:

[sourcecode language="text"]
192-168-1-3:bin gerrytan$ java -XX:+HeapDumpOnOutOfMemoryError LittleLeaker
java.lang.OutOfMemoryError: Java heap space
Dumping heap to java_pid280.hprof …
Heap dump file created [92624139 bytes in 0.306 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:2760)
at java.util.Arrays.copyOf(Arrays.java:2734)
at java.util.ArrayList.ensureCapacity(ArrayList.java:167)
at java.util.ArrayList.add(ArrayList.java:351)
at LittleLeaker.main(LittleLeaker.java:28)
[/sourcecode]

Let’s Analyze The Heap Dump File

  1. Make sure you have the latest JDK installed and configured on your PATH environment variable. Run jvisualvm program on command line. If this is the first time you’re running it, it might perform some calibration first.
  2. Load the hprof file by using the menu File -> Load. Select the file format to “Heap Dumps” and point to the path of the hprof file generated earlier
  3. Once loaded, you can see some basic information like when was the dump taken, environment properties, system properties, but most importantly the Threads at the heap dump section. Click the Show Threads link underneath it

    Recall that your virtual machine is a multithreaded environment. In our case, since it’s just a very simple app, you would be interested in the “main”thread.You can trace down in the main thread stack trace the culprit of the OOME.You might be thinking this is not so cool because you’ve already seen the stack trace from the console anyway. But think about if this were your Java EE app server with dozens of threads, getting to know what other threads are doing will be handy
  4. Another interesting analysis to perform is the Classes button at the top. This will show you total number of instances in the heap per classes

    As you can guess, this might not look so interesting since our program is just very simple. But when you have a real ly-complex enterprise application, then this information will be very helpful

There Are Heaps Other Tricks and Techniques

The functionality of Jvisualvm doesn’t stop there. You can also attach it to running JVM to see live monitoring data, obtain thread dump, profiling and plenty others.

This article written by Oracle’s Mandy Chung is a very good reading to deepen your knowledge about java application monitoring.

Leave a Reply