The Power of Aggregation: Making sense of the Objects in a Heap Dump
The goal of this article is not to provide you with a step-by-step approach in finding memory problems, but to reveal several powerful features of the Memory Analyzer, which are irreplaceable in memory leak hunting. These features might be unified into one topic – aggregation.
Memory Analyzer - is a powerful Java heap analyzer. It makes it possible to find a memory leak or reduce memory consumption by looking into the heap dump only. Our wiki page provides detailed information on how to acquire a heap dump.
Sometimes you open a heap dump in Memory Analyzer and see nothing … but a pile of small objects:
As overview pane shows, the majority of retained memory is more or less equally distributed among several objects, which makes it difficult to see a suspect for a memory leak at first sight.
Grouping in Dominator Tree
The pie in the overview pane is a graphical representation of the Dominator Tree, which you can open from the toolbar using the button 
The Dominator Tree is built out of an object graph. Each object in the tree is responsible for keeping its children alive. The tree is sorted in descending order according to the size an object retains in memory.
Now, if we group the dominator tree by class (using the drop-down toolbar menu), we will see a different picture:
We can see that 700 objects of class com.foo.bar.menu.MenuEntry retain 46 % of the total heap space. Suddenly we see an unequal distribution of the retained memory.
How is it possible that we see it only now? The answer is that in this heap dump we do not have one single big object, but a group of leaking objects. Remember, the overview page of the heap dump only displays the distribution of retained memory heap on a per-object basis. So, when we group the dominator tree by class, we group our leaking objects to their origin class and thus get an accumulated retained heap.
Let’s find out who is referencing all those com.foo.bar.menu.MenuEntry objects. For this select List objects –> with incoming references from the context menu. As a result we will get an object reference graph:
If we drill down into the com.foo.bar.menu.MenuEntry, we can see the chain of objects referencing our suspect. Unfortunately, in this case it is not really helpful as we see only a LinkedList structure.
Grouping referrers to the class level
As we have seen looking at the incoming references graph for our suspect objects did not reveal a lot. Grouping referrers to class level might be more helpful. This operation is performed via a context menu. Back in the dominator tree grouped by class, right-click on our suspect com.foo.bar.menu.MenuEntry and select Show objects by class –> by incoming references:
Grouping referrers by class allows us to see a simple and easy to understand reference chain:
We can now see, that class com.foo.bar.menu.MenuEntry is referenced by a LinkedListEntry, which we already knew. But as we continue we see that this entry is again referenced by a LinkedListEntry (this is the head of the LinkedList) and by the LinkedList. LinkedList itself is referenced by two classes, one of which is of no interest as it is from the java.* package (which for now we assume to be unproblematic). The other one, however, is of interest.
The easiest way to find out what keeps our memory leaking group of objects alive in the heap is to check the path to the garbage collection roots. However, paths to garbage collection roots can only be found for a single object but we are interested in finding a common chain of references to a group of objects. Well, this is also possible.
Merging Paths to Garbage Collection Roots
The Merged Paths to GC Roots view shows the shortest paths from the GC roots to each instance of the selected class. You can open this heap editor using the context menu Merge Shortest Paths to GC Roots on the com.foo.bar.menu.MenuEntry class instance:
This operation explores all the paths from the different objects to their GC roots at once and finds a common chain of references for this group of objects. It is a common procedure to exclude weak and soft references from the result as they cannot be the main reason of keeping the objects of interest alive.
There we got the reason: one instance of the class com.foo.bar.menu.FoodSupplies keeps in memory 700 instances of the class com.foo.bar.menu.MenuEntry. Now is the right time to check what is going on in the code and fix the problem.
Conclusion
Apparently, Memory Analyzer has more aggregation features to offer. Some of them will be covered in our future blogs.









May 8th, 2008 at 8:01 pm
Thanks for this new post. I have been using the memory analyser several days and find it very useful. Two features I miss currently :
- Ability to go quickly into the java code of a class. (When you are in the memory analyser perspective, ctrl+shift+T key binding is not active)
- Completion when enter an OQL query
May 9th, 2008 at 10:32 am
Mariot:
> Ability to go quickly into the java code of a class.
The analysis of the heap dump is performed offline and has no impact on the running application. Unfortunately, that also means that it is not possible to jump into the java code.
> Completion when enter an OQL query
Please add a new feature request to the Bugzilla. Or are you willing to contribute?
Elena.
May 9th, 2008 at 2:54 pm
Elena, thanks for the reply :
> The analysis of the heap dump is performed offline and has no impact on the running application.
> Unfortunately, that also means that it is not possible to jump into the java code.
I meaned only open the java source file from the contextual menu or a keybinding
> Completion when enter an OQL query
> Please add a new feature request to the Bugzilla. Or are you willing to contribute?
Due to lack of time I will start by opening new feature requests for the moment.
May 9th, 2008 at 3:00 pm
Mariot:
> I meaned only open the java source file from the contextual menu or a keybinding
Right:) We will enable the key binding.
Elena.