Where parallels cross

Interesting bits of life

JVisualVM, or how to observe the state of your Java Virtual Machine

Software engineers are very smart and do a lot of incredible work. Sometimes they also do errors of omission. Since I am an engineer too, I am prone to forget that the programs I write can cleanup for me until a certain point.

When we run a computation we typically create data that we store in some volatile memory. We got a stack, very small and fast, and a heap, very large and slightly slower.

If we overfill the stack with data, our software will complain by crashing the application with the infamous StackOverflowError:

def letsStackOverflow (list: List[Int]): Int =
  list match {
    case Nil => 0
    case x::xs => x + letsOverflow(xs)
  }

letsStackOverflow(1 to 10000 toList)
java.lang.StackOverflowError
...

Now the heap is another kind of beast. It is supposed to hold quite some data, so filling it will take time: your application will crash for lack of resources over time. Let's get a OutOfMemoryError for completeness:

import scala.util.Random

var listOnHeap: List[String] = List()

def letsHeapOverflow (list: List[Int]): Unit =
  list.foreach(_ => listOnHeap = s"someStringThatTakesHeapSpace_${Random.alphanumeric take 10 mkString}"::listOnHeap)

letsHeapOverflow(1 to 10000000 toList)
java.lang.OutOfMemoryError: Java heap space

In this example we willingly tried to fill up the heap as fast as possible. In real world scenarios this happen quite more slowly, creating subtle bugs that require very expensive hunting sessions.

Our hound when we are blindly looking for the bug in a Java Virtual Machine application is JVisualVM. It comes with your installation, so you can just fire it up by running jvisualvm in the terminal.

JVisualVM will pick up any processes that are using the virtual machine. So if you try to run the Scala code snippets above in a shell like Ammonite, you will see the ammonite process appearing in there.

If you click on this process, you will land on the overview for the process:

JVisualVMOverview.png

The information we are looking for is in the next view "Monitor":

JVisualVMMonitor.png

In this view you can see how the heap grows on the top-left diagram.

The other tool you want to look at is "Heap Dump" button. By pressing you obtain a detailed snapshot report for what the heap contains:

JVisualVMHeapDump.png

You will see that for our run of heapOverflow we have quite few strings, integer and colons. With this clue is at least easier to find which part of the code is causing the failure.

The usual next step is to println around until you find the problem.

Hope this will help your bug hunts.

Happy coding!

Comments

comments powered by Disqus