The Memory Analyzer Tool (MAT) is the recommended tool for analyzing heapdumps and system dumps, whether to find the cause of an OutOfMemoryError (OOM) or memory leak, to size a JVM, or other types of debugging. The tool is available for free with the IBM Support Assistant Workbench (ISA) or it can be downloaded from eclipse.org and extended with updates to support IBM dump types.
One common memory issue is a Java memory leak. This is not like a traditional memory leak in C/C++ where memory is mis-managed, but rather that the application references too many objects for too long given the constraints of the JVM. These are most often caused by object caches. This article will demonstrate how to use MAT to determine the cause of Java memory leaks.
First, a few notes:
- From MAT's Help Contents: "Object IDs which are provided in the heap dump formats supported by MAT are just the addresses at which the objects are located. As objects are often moved and reordered by the JVM during a GC these addresses change. Therefore they cannot be used to compare the objects. This basically means that if one compares two different heap dumps (although from the same process) it is not possible to point to the concrete objects different between the two heap dumps. However, one can still perform comparison on the aggregated results (e.g. the class histogram) and analyze how the amount of object and the memory they take has changed."
- When MAT loads a dump, any objects that appear unreachable are considered garbage and removed from the snapshot (unless an option is used to change this behavior). This means that you don't have to worry about, for example, taking a heapdump with a large amount of garbage in it, which is often the case when using a generational garbage collection policy.
Next, you'll need to acquire two or more heapdumps from the same JVM over a period of time in which the leak occurs. In general, a longer time period is better because the leak will be easier to pick out from random & temporal increases. For information on how to dynamically acquire heapdumps, see http://www.ibm.com/developerworks/websphere/techjournal/1103_supauth/1103_supauth.html.
MAT supports loading multiple heapdumps at once. You'll probably need a large maximum heap size for MAT itself and you may need a 64-bit version of MAT.
Load the first and last heapdump. Next, select the latest heapdump, and click the Histogram button:
Click the button to compare to another heapdump: (This button will not appear if there is only one heapdump loaded.)
Select the baseline dump (i.e. the first dump) and click OK:
This will show a comparison of the class histograms between the two dumps, sorted by shallow size. In the above example, the latest dump has 20MB more of byte arrays, although there are 19,145 fewer of them (this means that the average size of a byte array has increased). As with class histograms in general, you often want to skip past primitives, Strings, and collections, in this case taking us to 21,998 more instances of RemovedEntry, taking up 703,995 more bytes of shallow heap. At this point, there is no science to discovering the leak (unless it's obvious), but one approach would be to see if the "uncommon" classes are holding the "common" classes; i.e. do the RemovedReaper and TTLHeapEntry objects retain HashMap entries? We can see just by the object counts that it is likely, and therefore, those uncommong objects are a leak suspect.
Recent versions of MAT have extended differencing capabilities beyond the class histogram by introducing the compare basket. Explore the "Comparing Objects" topic in MAT's Help Contents for more information.