Jinsight Guided Tour
Execution Pattern View
Reference Pattern View

Exploring Data Structures · Finding Memory Leaks

This section gives a brief look at the Reference Pattern view.  Its forte is summarizing references among objects.  It's especially useful for exploring data structures and finding memory leaks, which can occur even in a garbage-collected environment like Java's.


next: Finding Memory LeaksExploring Data Structures

Start Jinsight afresh on RPExample1.
 
To start Jinsight with the RPExample1 trace:
  1. Choose Start => Programs => Jinsight2.0 => Jinsight Visualizer.
  2. Choose Workspace Window => File => Open Trace File....  An "Open trace..." dialog box will appear.
  3. Go to the traces subdirectory.
  4. Double-click on RPExample1.trc.

Load the whole trace before viewing it. That will let the Reference Pattern view read the object reference information at the end of the trace.
 

To load the trace:
  1. Press Workspace Window => Load.
  2. Wait until the end of the trace is reached (i.e., when all trace events have been read, as indicated by the Workspace Window).
  3. Choose Workspace Window => Views => Reference Pattern.

The view comes up blank initially. The first thing to do is to choose a base set of objects to explore.  Let's limit our our base set to objects in application code, as opposed to library code.  Specifically, we will omit objects from the JDK, which tend to be plentiful but less interesting than objects you've programmed yourself.
 

To show all non-JDK (and non-array) objects:
  1. Choose Reference Pattern => Start with => Non-JDK and Non-Array Objects.

Squares in the view represent either a single instance of a given type (if it's a single square) or multiple instances (represented by twin squares). Diamonds represent class objects. Objects are colored uniquely by type as in the Execution and Execution Pattern views. The precise number of objects and their type appears to the immediate right of a square or diamond. Objects in the gray area make up the base set from which to explore references.  Arrows between objects represent references. An arrowhead points to the object being referenced.

The base set of objects is sorted by number of references by default, in decreasing order.  The view stays sorted at all times, which makes it easier to find large groups of references.  But when you are exploring references, as we are about to do, automatic sorting tends to get in the way—the tree can change out from under you as you navigate it.  So we'll turn sorting off for now.
 
To turn sorting off:
  • Choose Reference Pattern => Options => Sort by Number of References.

Now scroll down to the bottom of the view. Your view should look like this:

The diamonds at the bottom represent class objects. The blue diamond, for example, represents the class object for StdDrawStrategy (abbreviated "StdDrawStrate"; you can see the full name in the status line when you fly over the diamond or its name). No other objects keep a reference to this class object.

Above these class objects is an orange square-and-diamond combination representing three objects related to the ShadowFramer class: one is the class object, and the remaining two are regular instances. Farther to the right are several objects—some you may have to scroll to see—that refer to one or more of the ShadowFramer objects. But even if you scroll or resize the view window, you still can't see everything.  It's not clear who refers to whom, because you can't currently see the ShadowFramer objects individually.  To do that, you ungroup the orange diamond-square.
 
 

To ungroup the ShadowFramer objects:
  1. Right-click on the orange diamond-square.
  2. Choose Ungroup Objects.
  3. Enlarge the window vertically so that the three ungrouped ShadowFramer objects are all visible.


Now you can see who refers to each of the three ShadowFramer objects. There are no references at all to the class object (the orange diamond). The first of the instances has six references (2 from Object and one each from Label, LightweightDispatcher, HashtableEntry, and WPanelPeer). These objects in turn are referenced by others, and so on.

Note the blue upward arrow annotated "backpointer" (on the right) in the figure above.  The blue arrow calls attention to the fact that this instance of ShadowFramer is actually a reappearance of the ShadowFramer instance above it in the tree.  Thus in this case we see a circular reference: the first ShadowFramer instance refers to the LightweightDispatcher, and vice versa.  A blue arrow accompanies repeat appearances of objects to help you find the original appearance.
 

To locate the original ShadowFramer square:
  • Left-click on the blue arrow marked "backpointer."

The blue arrow now extends to the original orange ShadowFramer square. (Left-click again at the base of the blue arrow to remove it.)

Not all references are shown in the view. Squares with a "+" appearing in a box to their left have hidden references to/from them.
 

To see hidden references:
  • Left-click on a "+" box.

The tree of references will expand to show the hidden references to/from this object(s).
 

To expand all squares at a given depth in the tree:
  • Push the button marked with a right arrow (and labeled Depth) at the top of the view.

Note that reference arrows are drawn right-to-left by default.
 

To see the references drawn in the opposite direction (left-to-right):
  • Press Reference Pattern => >>>.

 
To return to the default direction:
  • Press Reference Pattern => <<< (the same button toggles the direction of references).

Use these navigation mechanisms to explore the space of references and to study data structures such as trees and linked lists.


next: bottom of pageFinding Memory Leaks

Say your program creates temporary objects that you expect to be garbage collected. But you notice in the Histogram view that some of these objects never get collected because, unbeknownst to you, one or more non-temporary objects still refer to them. The problem is to identify these non-temporary anchor objects so that you can eliminate the spurious references.  The Reference Pattern view helps you do that.
 
To find the anchors:
  1. During the trace-creation process, identify old-generation objects.  You do that by marking a point in your program's execution just before the creation of the leaked object(s)—that is, those that should be reclaimed after a garbage collection but aren't. You mark the point using the dump population tracing command.
    For example, suppose your application creates a dialog box that should be collected after the user finishes with it.  The point in question occurs just before the dialog box gets created—the old generation ends at that point.  Objects created after that point are called new-generation objects.
  1. Continue executing to a point where no references to leaked objects should remain.  You mark that point using the dump population and references tracing command, which records a snapshot of all the objects and memory references in the trace. Then you terminate the program manually.
  2. Examine this trace using Jinsight, letting it run to completion before popping up the Reference Pattern view.
  3. Use the Reference Pattern view to find the old-generation objects that refer to leaked objects in the new generation. These old-generation objects are the anchors that keep leaked objects from getting collected.

RPExample1.trc is in fact a trace that helped us find a memory leak in Jinsight itself. Jinsight's performance degraded noticeably after using many views on a large execution, even though we never had more than a few views open at a time.  Now we'll use the Reference Pattern view to track down the leak (we needn't rerun the trace).

Since we're looking for references to new generation objects from the old generation, we tell the view to start with new generation objects. In particular, we will first focus on objects of user-defined classes that aren't being collected. Solving a memory leak in one of these classes often will allow lower-level objects, such as JDK objects and arrays, to be released.
 

To start with a base set of application objects:
  • Choose Reference Pattern => Start with => Non-JDK and Non-Array Objects in New Generation.

Note the base set. It contains all the new-generation application objects (including class objects but not arrays). Either old- or new-generation objects can appear outside the base set; new-generation objects outside the base set are repeat appearances.

In this trace, the new-generation objects were created when we opened and immediately closed an Execution view in the leaky version of Jinsight. The text in the upper left of the base set area indicates that there are 34 new-generation objects.  Most if not all of these objects should eventually get collected—assuming no anchor objects from the old generation still refer to them.
 

To single out the anchors:
  • Choose Reference Pattern => Options => Expand to Old and Class Objects.

Now references in the view are expanded only enough to see those from old-generation objects. Scrolling down, you will see there's only one reference from an old-generation object. It's easy to see because its name appears in red:

One of the five references represented by the twin gold squares is from an old object. You can ungroup the gold squares (right-click on the squares and choose Ungroup Objects) to see which one. That reference will prevent that object's garbage collection. Severing that reference in the code eliminated the leak.


Execution Pattern View
Jinsight Home