Friday, July 25, 2014

Demystifying Java Dumps

I have never taken dumps of an application to help with debugging. I can think of a couple of instances when it would have been helpful, but at the time I did not know about them. Now I hear more about thread dumps and heap dumps and feel like they should be in my toolkit.

In this post I will just try to touch on what the dumps will contain, why they are useful, and how to get started interpreting them. This is by no means a comprehensive analysis. There are several different JVM and OS-specific ways to trigger dumps (signals, environment variables, JVM command-line options), their content varies by JVM, and there are multiple tools for analyzing them.

I am using 64-bit Oracle SDK 1.8 on Windows 7 because that is what I already had available.

Thread Dumps

thread dump is a snapshot of all threads in a process, including their stacks. It can help you diagnose problems like deadlocks. By taking several consecutive thread dumps you can also detect bottlenecks like multiple threads vying for the same lock.

To create my thread dump I simply ran Ctrl+Break from the window my server was running in.

To analyze my thread dump I tried out the Thread Dump Analyzer (TDA). I provided three thread dumps about five seconds apart and it found my deadlock:

Program that intentionally deadlocked two threads

Heap Dumps

A heap dump is a snapshot of the memory of a Java process, including everything in the JVM heap space. It is useful for figuring out why you are running out of memory.

To create my heap dump I set the -XX:+HeapDumpOnOutOfMemoryError JVM option, but to create one interactively I could also have used the jmap tool: jmap.exe -dump:live,format=b,file=<file name> <pid>

To analyze my heap dump I used the Memory Analyzer Eclipse plugin which shows things like:
  • a histogram showing the number of instances per class
  • dominator tree - a list of the biggest objects and what they keep alive (shown below)
  • top consumers - the most expensive objects grouped by class and package
  • classes loaded by multiple class loaders
  • memory leak suspects
  • top components - components bigger than one percent of total heap
Program that intentionally caused an OutOfMemoryError by creating a large list