Main Points to Hit
- The HeapWalker provides a complete picture of the objects on the heap and the references between the objects.
- Is especially useful for analyzing binary heap dump files produced when an OutOfMemoryError occurs.
- Find Nearest GC root feature can help track down memory leaks by showing the reference that prevents an object from being garbage collected.
- NetBeans 6.0 M10 (or higher)
- Download the attached PrimeNumbers project
- Open the PrimeNumbers project
- Profile the PrimeNumbers project at least once so that the IDE can add the profile target to build.xml
- Right-click PrimeNumbers and select Properties; then select Run. Verify that VM Options is set to -Xmx6m
- Right-click the PrimeNumbers project and select Profile Project
- Click the Monitor button on the left side of the dialog and then click the Run button. Suggested Comment (SC): "Okay, so here's a silly little prime number generator."
- When the UI displays, make sure that the IDE's window is visible in the background. In the application's "Enter a number" field type in 1000000 (that is a one followed by six zeroes) and then click the Calculate Prime Numbers button. SC: "I put in a number and then it will calculate the largest prime number less than or equal to that number."
- The result displays 999983. SC: "That was quick! Now if I click the button again it should be even faster because this program caches the answers it calculates...."
- Click the Calculate Prime Numbers button again. The application dies with an java.lang.OutOfMemoryError: Java heap space, which is visible in the Output window of the IDE. SC: "Uh-oh...."
- Switch to the IDE window. It will pop up a dialog asking if you want to open the heap dump that was generated in the heapwalker. Click Yes. SC: "An OutOfMemoryError was thrown so the profiler requested a standard binary heap dump snapshot from the JVM. We can open it in the profiler's heapwalker to take a look at what is on the heap."
- The heapwalker opens up with a Summary view. SC: "We can see the summary here: size, operating system, and the JVM system properties."
- Click the Classes button and then click the Size column to sort by size:
- SC: "This is a list of all the classes that are on the heap, along with the number of object instances of each and the total size occupied by those object instances."
- Click on the first line, which is for int array in order to highlight it. SC: "Hmmm... looks like most of the heap is taken up by int arrays. Let's take a look at the object instances for int array."
- Right-click the int array entry and choose Show in Instances View. SC: "There are over 2,000 int arrays on the heap, but the instances view sorts them by default by size. The first one listed is the largest and it has an interesting size: 4 million bytes. Hmmmm.... Let's take a look inside."
- Click on the first int array instance (the one that is 4 million bytes). SC: "Now that I have selected an instance, I can see two things over on the right: its fields and a list of any objects that reference this particular instance."
- Expand the <items 0-499> entry. SC: "Since this is an array, the list of Fields is actually a list of array indexes, in groups of 500. I've expanded the first group, let's take a look at what is in here...."
- Scroll down through the list. SC: "Hmmm.... Looks like this array holds all the prime numbers less than the requested value, with place holder entries for integers that are not prime."
- Close the Fields panel. SC: "We have found something on the heap that should not be there - in this case, this appears to be an array that was used during the calculation that should have been garbage collected after the calculation. So why didn't the JVM's garbage collector remove it? There must be some accidental reference to it that is being made (and that should be cleared). This is where the References information comes in handy."
- Right-click the entry for this in the References panel and click Show nearest GC Root. SC: "Garbage Collection roots are the objects that never get removed from the heap - they are the starting point for the JVM's garbage collector. Any object that is reachable from a GC root cannot be removed from the heap."
- The display expands so that the entry for primeNumbers is shown. SC: "There are actually several GC roots in this case, but what is often more interesting is what we can learn by looking at the object references along the way, since if they were to let go of their reference this array would be eligible for removal by the garbage collector. Notice this variable called completeResults_."
- Right-click completeResults_ and choose Go To Source. "An advantage of an integrated tool - easy access to the source code."
- The PrimeNumbers.java file opens up; the completeResults_ variable is on line 31. Right-click it and select Find Usages. SC: "Interesting. This is a Map - let's see where it is used."
- When the Usages window opens with the results, double-click the only result. SC: "Well, well, well. The complete list of candidate prime numbers is being put into this Map, but as we can see from the Usages results it is never removed. So we don't need the array anymore, but it cannot be garbage collected - that is a memory leak. And one easily found with the profiler's heapwalker." :-)
- Select Profile > Load Heap Dump. SC: "One last thing to note - the profiler's heapwalker can also be used on any binary heap dump file produced by one of Sun's JVMs. There are a variety of ways to get a JVM to produce a heap dump; as an example, there is a command line flag that you can use to have the JVM create the file whenever an OutOfMemoryError is thrown. You can then open that file with this feature."