A special case of memory profiling is Heap Browser. The JVM is capable of providing a snapshot of the entire JVM memory. This memory dump is assured to be the exact state of the JVM memory at the time the snapshot was taken. Such a heap snapshot can provide invaluable data in understanding how memory is allocated and used. Specifically, the Heap snapshot provides a summary of the classes, instances, allocations, out-references and in-references of the objects that are held in the heap at a particular time.
The heap browser can be accessed from the Navigational Tree by clicking on the Heap Browser node.
Click Take Snapshot to take a snapshot of the heap. After the snapshot is taken, a list of objects present in the heap at the time of taking the snapshot can be seen, the details of any class can be viewed by double clicking it.
By default, AppPerfect Java Profiler will take a memory snapshot of your JVM, but if you need to take snapshot of only selected classes, you can do that. The Snapshot Settings dialog box will show up when you click 'Take Snapshot'. Click the 'Add' button and add the class names that you want to include in the snapshot. Only the class names you will provide here will be available in the snapshot. If you want to add more classes after a snapshot is taken, you will have to take a new snapshot.
After a snapshot is taken, you are able to browse through the various summary tabs (described in the following sections). You can save the snapshot by clicking the save button. Also, if you choose to take a second snapshot you are given the option to save the current snapshot using a dialog box. You can choose to save or discard the snapshot. Snapshot names are by default created using the current datetimestamp. You can change this name when the save dialog box shows up.
These are the tabs in the Heap Browser: Packages/Classes, Allocations-Tree, Object Instances. If in the Classes view you detect that some classes are still being held live in memory which should have been garbage collected, you will need additional information on those classes for which you need to take a snapshot of the heap. You can then go through the details and of all the live individual classes, the objects and references to those objects and detect which objects are holding unnecessary references to the objects in memory.
After detecting these, you can fix your code, and run the AppPerfect Java Profiler again, and in the classes view detect if those objects are either not created or are indeed garbage collected. If those objects still show up as live objects, then you may need to take a snapshot again and correct your code. Ideally, once this is complete, there should not be any unnecessary objects live in memory.
In the Snapshots tab, you can see the table of all snapshots taken. You can save, delete, compare snapshots and select snapshots for which you want to see details.
In the Packages/Classes tab, you can see the heap memory snapshot in terms of packages/class. It gives you details about the number of instances and the size of the instance for each package/class. You can filter the data seen on package name or class name.
The Allocation tree shows the allocation of the memory in the heap. It is a tree structure with many nodes. The first level of this tree shows you the percentage of the total number of objects allocated in the particular class selected. At the second level the threads created by the application will be shown and the total number of objects that were allocated in those threads. At the next level you will see nodes which are the first function call starting from which one can traverse through the series of function calls made, ending at the function where actual object allocation was done.
The percentage allocation along with the Class Name and Total Number of Allocations is displayed at the top of the allocation tree and at every node of the Allocation Tree.
Instances tab contains the details for each object of that class that are present in the heap. The instances tab now shows you the Class name and No of object instances of the class selected in class table. The heading on top of the Field value table shows the Class name, Instance Id, Number of static and instance fields of the instance of which this table is showing the field values.
To the left the object id column is the object ID's for each of the objects of that class that were present in the heap when a snapshot was taken. Clicking any of the object IDs populates the table on the right with the corresponding data for that object. The table contains the field type, signature, field name, value and size of the selected object id.
While looking into the Field value table on the right, if the field is an instance, then the value shown in the Value column is its instance ID. You can double click this row, to see the field values of this instance. Similarly, you can see the field values of all the instances. The navigation buttons provided on top of this table can be used to look at previous/next instance fields.
This is extremely useful information to judge if there is any unnecessary information being held in memory, as a result of objects not being garbage collected and thus creating additional memory overhead. You can filter the data based on any of the column headings so that data most relevant to your analysis is shown.
You can see the details here.
You can see the Allocation Tree here.
To view the references of each of the object IDs in the Instances tab double click the Object ID or right click and select Show Incoming References. The Incoming References tab contains the reference tree of Incoming References. The Incoming References panel displays the classes and method that have referred the present object. To access Parent References, right click inside the Incoming References pane.
To view the references of each of the object IDs in the Instances tab double click the Object ID or right click and select Show Outgoing References. The Outgoing References tab contains the reference tree of Outgoing References. The Out References tab shows the classes and methods the object is referring to. If the object has created any objects those objects will be shown as Child References. To access Child References right click inside the Outgoing References pane.
Any garbage collection algorithm must do two basic things. First, it must detect garbage objects. Second, it must reclaim the heap space used by the garbage objects and make it available to the program. Garbage detection is ordinarily accomplished by defining a set of roots and determining reachability from the roots. An object is reachable if there is some path of references from the roots by which the executing program can access the object. The roots are always accessible to the program. Any objects that are reachable from the roots are considered live. Objects that are not reachable are considered garbage, because they can no longer affect the future course of program execution.
It's important to note that not just any strong reference will hold an object in memory. These must be references that chain from a garbage collection root. GC roots are a special class of variable that includes Temporary variables on the stack (of any thread), Static variables (from any class), Special references from JNI native code.
You can compare two or more snapshots taken at different points in time of the execution of your application under the AppPerfect Java Profiler's scrutiny. The comparison shows you the number of instances added and deleted from one snapshot to the other. This information can be very useful in finding the different state of the JVM over a period of time. It is saved with the name "SnapShot_Comparison_currentdatetimestamp", with the description including the names of the two snapshots that have been compared.
The way memory leak detection tool works is:
These objects are potential memory leaks, but clearly it's possible that all of them are not actual memory leaks. The way to find the real leak is to look at objects present in the memory and find the classes or objects which should not be present. So you need to know details of the target application being profiled. Now you should check if any other class or object is present other then the expected DS and classes. On finding one you should take a snapshot and look at GC root reference tree for those object instances that will help you find the actual reference which is preventing object from getting garbage collected.