Profiling memory use and debugging memory leaks in application code in the early stages of development is considered a best practice for application development. It can provide early detection of memory problems long before the production stage. Taking the time to profile and debug memory usage issues during proof-of-concept or development milestones will avert major architectural changes late in the application life cycle.
Before introducing the IBM® memory profiling and debugging tools, let us have a quick look at the issue itself -- memory management and memory leaks in Java™ and J2EE applications.
Garbage collection and memory management in Java applications
As a modern language, Java has an automatic memory management mechanism called garbage collection, which makes it much easier for you to manage
objects created in the application code. When an object is created by new keyword,
it is placed into the Java heap of the Java Virtual Machine (JVM). The JVM has a garbage collector, and when this object is no longer needed by any code,
the garbage collector removes it from the Java heap. Listing 1 is an example of a method defined in a Java class:
Listing 1. Example method in Java class
public void aMethod() {
String s = new String("My string"); // String is a Java class
}
|
In this example, a new String object is allocated in the Java heap. Unlike coding in C or C++, you don't need to write code to explicitly delete the object
from the heap after you're done with it. When the method is called and returned, the only reference to this String object, s,
is set to null and removed from the thread stack. The JVM garbage collector detects that the number of references to this String object is 0, indicating no code may access or use the object any longer. When the garbage collector has an opportunity to run, it treats this String object as garbage,
removes it from the Java heap, and frees the memory allocated for it.
The garbage collector frees you from manually releasing the memory used by the objects after you are finished with them.
Garbage collection makes code much safer, because explicitly deleting objects from memory is error-prone. However, garbage collection is not a panacea.
If you don't manage the references to the Java objects carefully, they may face another type of memory leak problem. In the above example, if
s, the reference to the String object, is not a local variable, but a instance variable or even a class variable (which exists for the life of the application), this reference may be valid throughout the life of the running application. The String object will never be removed from the Java heap.
This may be a desired effect, but if not, it's a memory leak.
When the IBM JVM is launched as an operating system process, it allocates two heaps for itself from the system memory. The first one is called the Java heap and contains the Java objects created by the system and Java applications. In the J2EE environment, it also holds the Java objects created by IBM WebSphere® Application Server (hereafter called Application Server). The second heap is called the system heap. It stores the objects that usually have a life expectancy of the life of the JVM, such as class objects and Java Native Interface (JNI) objects. Given that J2EE applications usually do not cause memory leaks in the system heap, the rest of this article shows you how to use IBM tools to deal with memory leaks in the Java heap.
Usually, solving a memory leak problem is a two-step process: identifying which Java classes caused the memory leak, and then determining where in the application the leak occurred. The goal of the first step is easy to achieve with the tools. The second step is more challenging, because tracking the relevant information in a profiling tool slows down performance. The profiler discussed in this article does not provide the detailed information needed to track down the source of memory leaks in the code, partly because of performance considerations. Some tools may be configured to collect such information with significant adverse impact on performance, such as Hprof and other third party tools. Given the scale of J2EE applications and the J2EE environment associated with them, performance concerns often prevent developers from tracking sufficient information using those tools.
To simplify the discussion of resolving the difficulty in the second step in this article, memory leaks are divided into two types.
- Rarely used object leak
- A memory leak in which the leaked Java object belongs to an infrequently used Java class. In a J2EE environment, a JVM often holds millions of objects, some created by Application Server and others are created by applications running inside Application Server. Typically, the objects of an application-defined Java class are only created and referred to in a limited number of places in the application. The leaks of these objects often belong to this type. In this scenario, the second step of identifying the leak is straightforward. Because the objects that belong to the same class of the leaked object are only used in a few places, you can easily locate the source of the memory leak by checking the application code where these objects are used.
- Frequently used object leak
- A memory leak in which the leaked object belongs to a widely used Java class. Many Java classes in standard java and javax packages, as well as in
utility Java classes defined in applications, are frequently used classes, such as
java.lang.String. In this scenario, the second step of the process can be difficult. Without sufficient information, it's hard to locate the code causing this type of leak, because objects of the same type are defined in numerous places in applications, and even in WebSphere Application Server. Checking all the places where these objects are used is far too time-consuming.
To resolve the difficulty of the frequently used object leak, obtaining the object reference chain that contains the leaked objects is very helpful. With this information, and some familiarity with the application, you can often find the memory leak code with little effort. For example, object A has a reference to object B, object B has a reference to object C, and object C is the leaked object. Object A, B, and C form an object reference chain, denoted by A=>B=>C. If this chain is long enough, or if any object in this chain is a rarely-used object, the chain is quite distinctive. It can then be mapped to the source code to identify which object C is actually the leaked object. The IBM JDK and its support team have provided the tools to obtain this information with minimal performance impact. By analyzing these reference chains, you can find which chain is relevant to the memory leak and use this chain to locate the source code where the leaked objects are allocated. For a step-by-step example, see Heapdump and HeapRoots.
Overview of profiling and debugging tools
As the premier integrated development environment for J2EE applications, Application Developer provides a Profiler tool to diagnose memory leak problems in J2EE applications. Also, the IBM JDK utility Heapdump, and a standalone heapdump analysis tool called HeapRoots, are more powerful tools for debugging memory leaks. The Profiler is fully integrated with Application Developer and is ideal for identifying rarely used object leaks in Application Developer. For frequently used object leaks, the information provided by the Profiler may not be enough, and you will need to use Heapdump and HeapRoots to find the memory leak.
The IBM JDK also has a utility called Hprof. Like the Application Developer Profiler, Hprof uses the Sun Java Virtual Machine Profiling Interface (JVM PI) to collect the profiling information from the running JVM. It can provide detailed stack trace information about the memory allocation in each thread. This article will not describe this tool because Heapdump and HeapRoots are better choices for J2EE developers. For more information on Hprof, see IBM JVM Diagnostics Guide.
To monitor garbage collection activities, turn on JVM verbose garbage collection (verbosegc), which often gives you a good idea whether there is a memory shortage in the Java heap. To learn more about how to turn on the verrbosegc option for the Application Server process in the WebSphere Administrative Console, see Web module or application server dies or hangs in Application Server InfoCenter and search on "garbage collection."
The following table compares these tools.
Table 1. Comparison of profiling and debugging tools
| Tools | Description | Advantages and suitability | Disadvantages |
| Profiler | Application Developer Profiling tool for inspecting the performance of applications |
|
|
| Heapdump/HeapRoots | JDK Utility for generating heapdump/Standalone heapdump analysis tool |
|
|
| Hprof | JDK Profiling tool for inspecting the performance of applications |
|
|
This article uses Application Developer V5.1.2, its embedded copy of WebSphere Application Server V5.1 (also called the WebSphere Test Environment or WTE)
and HeapRoots HR205.jar on Windows 2000 to demonstrate how to use these tools to debug memory leaks in J2EE applications.
Application Developer Profiler
The Profiler provided by Application Developer is a tool to inspect the performance of Java applications. The application profiling is made possible by using the standard JVMPI interface. A JVMPI implementation (known as the agent) runs as part of a standard JVM. The agent receives and records information from the JVM, such as memory allocation and thread activities. The agent may also request additional information or deactivate further notifications of specific events by configuring the Filter feature in the Application Developer Profiler. The Profiler uses the IBM Agent Controller to communicate with JVMPI agents and collect the performance information. You can use the Profiler on local or remote Java processes and even on distributed applications. Processes can be launched for immediate profiling or the profiling can attach to an existing process.
This article focuses on how to identify and isolate memory issues by using the memory usage information collected by Application Developer Profiler..
The Profiler has several views to show profiling data. Three of them are relevant to our discussion: Class Statistics view, Package Statistics view, and Instance Package Statistics view. Using any of them, you can solve rarely used object leak problems. You can easily identify the leaked object based on the number of object instances or the total size of these object instances. Since the leaked object is used only in several places in the application, its location can be identified based on its class and package name. However, if the leak is caused by frequently used Java classes such as java.lang.String,
you need to obtain additional information by collecting and analyzing the heapdump with the IBM JDK tools discussed below.
Sample application for rarely used object leak
The two sample applications used in this article are packaged in memLeakApp.ear, which you can
download below. Listing 2 shows the sample code of the first application:
Listing 2 Rarely-used Object Leak sample code
public class MemLeakServlet extends HttpServlet implements Servlet {
MemLeakClass[][] leakArray;
public void init() throws ServletException {
super.init();
leakArray = new MemLeakClass[1000][1000];
}
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
for (int i = 0; i<1000; i++)
for (int j= 0; j<1000; j++)
leakArray [i][j] = new MemLeakClass();
try
{ resp.getWriter().println(" The MemLeakServlet has been invoked."); }
catch(Exception e)
{ System.out.println(e.toString()); }
}
}
public class MemLeakClass {
public String leakString;
public MemLeakClass() {
leakString = new String("abcdefghijklmnopqrstuvwsxyz abcdefghijklmnopqrstuvwsxyz " +
"abcdefghijklmnopqrstuvwsxyz abcdefghijklmnopqrstuvwsxyz abcdefghijklmnopqrstuvwsxyz");
}
}
|
In this example, two classes are defined to simulate a rarely used object leak. The first class is a servlet called
MemLeakServlet. The second class is a simple Java class called MemLeakClass, which is the class of the leaked object. Because class MemLeakClass has a String variable, the String is a leaked object as well.
MemLeakServlet has an instance variable called leakArray. It is a 1000 * 1000 two-dimensional array that contains a million
MemLeakClass object instances. Application Server's Web Container only loads one servlet instance for each servlet
during the lifetime of the application. Therefore the array leakArray will not be garbage collected unless the application is stopped
and the servlet is unloaded by the Application Server runtime. This situation introduces a memory leak because the one million
MemLeakClass objects are referenced by
leakArray and are kept in the Java heap for the lifetime of the application.
The Profiler requires the correct version of the IBM Agent Controller to be installed. The Agent Controller is shipped with Application Developer and you can install it
using launchpad.exe, the Launch Pad of its installation image.
Steps for profiling the sample application
To profile this sample application in Application Developer:
- Go to Windows Service panel and make sure the IBM Agent Controller is started as a service.
- Import the sample application into Application Developer.
- Configure a server in the Server perspective and add the application into the server.
- Start the server in profiling mode: right-click the server and select Profile in the pop-up menu.
- Configure the Profiler (see next section for more details).
- Start the Profiler monitor in the Profiling and Logging perspective.
- Run the sample application.
For details on using the Profiler, see J2EE Application Profiling in WebSphere Studio, or the Help menu (Information Center) of Application Developer. The following sections describe how to configure the Profiler and run the sample application:
When the server is starting in profiling mode, a profiling wizard is automatically invoked. Use the wizard to configure the Profiler. Usually, the default WebSphere J2EE filter set is the best choice to start with. In this example, the most valuable information needed to identify the leak is the total number of object instances of MemLeakClass and String. But the default filter sets will filter out all the classes in package java.*, including String. To avoid this, you must configure a new filter set in this wizard. The major steps of the Profiler configuration are described below and the selected options are indicated in the following figures.
- From the Agent page, select the agent for the application server process (such as
Unknown[PID:2252]) in the Agents panel and move it to Selected agents panel on the right side. - Click Next twice and skip to the Profiling Filters page.
- In the Profiling Filters page, click Add on the right side of the Select a filter set panel and add a new filter set called
memLeak(See Figure 1). Select this new filter set. The contents of panel are updated to reflect the filters defined in this filter set:
Figure 1. Creating a new filter set

- To add a new filter in the just created filter set, click Add on the right side of Contents of selected filter set panel. Then specify the package name
and the rule for the new filter in the Add filter pop-up (see Figure 2). In this example, the package name is
java.lang.*and the rule is INCLUDE. Figure 3 shows the Profiling Filter page when these steps are done. Click Next to go to the next page.
Figure 2. Adding a new filter

Figure 3. Created a new filter in the new filter set

- Keep the default settings for Profiling Option page and click Finish to close the wizard.
Now, the Profiling and Logging perspective is opened in Application Developer. Select the first profiler (Java Profiling Agent) of the server process in the Profiling Monitor view and click Start Monitor to start the profiler. By default, there are two profilers for each process:
- Java Profiling Agent
- J2EE Request Profiler
Java Profiling Agent is listed as Profiling in Profiling Monitor View. This is what you will use to profile the application. J2EE Request Profiler is not used here.
Profiling the sample application
After configuring and starting the Profiler, use the following steps to profile the application server process in which the sample application runs:
- Open a Web browser inside (or outside) of Application Developer.
- In our example, a JSP is used to invoke the servlet
MemLeakServlet. The URL for the JSP on the local machine ishttp://localhost:9080/memLeakWeb/welcome.jsp. Click Invoke servlet in the JSP to run the servlet. - After the servlet returns the message
The MemLeakServlet has been invoked, go to the Profiling and Logging perspective, select Java Profiling Agent of the server process, and check either of the two views: Class Statistics view or Package Statistics view.
The views mentioned in Step 3 show that there are a huge number of String and MemLeakClass object instances, which
indicates that they are the leaked objects. Even if you run garbage collection manually from the Profiler Monitor view, these
MemLeakClass and String object instances are still in the memory.
MemLeakClass is a rarely used Java class, which means the locations of this type of objects in the application code can be easily identified. By checking the code of MemLeakClass, it is also obvious why there is a leak for the String object as well: each
MemLeakClass object has a String instance variable pointing to a String object. Thus, the information provided by the Profiler
is enough to solve this kind of memory leak. Figure 4 shows the Class Statistics view in the Profiling and Logging perspective:
Figure 4. The Class Statistics view

The above example shows that the Application Developer Profiler is good for identifying rarely used object leaks. As mentioned before, it may not be able to provide enough information for a frequently used object leak. For example, if the Class statistics view shows that only String object is the leaked object, it would be hard to determine where the memory leak is in a reasonably sized J2EE application, because String is a common Java class and it is used in many places throughout applications. Fortunately, that is where Heapdump and HeapRoots come to the rescue, as described below.
There is a performance impact when using the Profiler in Application Developer. When Application Server runs in profiling mode, it runs more slowly. On the other hand, the Heapdump tool discussed next causes little performance degradation because the overhead is incurred only when the Heapdump is actually performed.
Heapdump and HeapRoots are powerful tools for debugging memory problems. They are commonly used by IBM product support teams to analyze memory issues in the WebSphere environment, and they provide the useful information needed to diagnose most Java memory leaks.
Heapdump is a utility shipped with the IBM JDK. It lets you dump all the living objects in the Java heap into a text file, called heapdump.
The heapdump generated by the Heapdump utility is huge and difficult to read. It contains millions of items recording the objects stored in the Java heap. HeapRoots is a much-needed tool to analyze the heapdump and provide the information to investigate memory issues. For instance, HeapRoots can provide a list of objects sorted by size, or by total size of the subtree of the objects. The subtree of an object may contain all the objects to which this object refers, directly or indirectly, including itself.
HeapRoots can also traverse the heap, organize the objects into a tree structure based on their reference relationship, and write them to the output as indented trees. The roots of the trees are the root objects in the Java Heap. The HeapRoots output may filter out the small objects based on a threshold of the total size of the object's subtree. Most of the time, the objects' property, the total size of the subtree, can help you discover the leaked object. For example, in the first sample application,
MemLeakServlet is the object that has references to the leaked MemLeakClass objects. Each
MemLeakClass has a reference to a String object. Hence, MemLeakServlet's subtree contains all the
MemLeakClass objects and the String objects referred to by those MemLeakClass objects. Therefore, the total size of MemLeakServlet's subtree is very large because it is greater than the sum of the sizes of those
MemLeakClass and String objects.
By identifying the root objects with a large subtree size in the HeapRoots output and scanning the objects in these subtrees, you can easily chase down
MemLeakServlet from a root object along the reference chains and find that this servlet contains a large number of
MemLeakClass objects, which is the indicator of a memory leak in this class. Based on the objects in this object reference chain, the location of the memory leak in the source code can be identified as well. Hence, Heapdump and HeapRoots provide the critical information needed to solve a memory leak problem, even for the case of frequently used object leak, as mentioned in the section Finding Memory Leaks.
This article does not cover the all features and functions of HeapRoots. For more information, see the HeapRoots documentation on the HeapRoots Web site. This article shows you how to enable Heapdump and generate a heapdump in the Application Developer environment, using an example to show you how to identify the memory leak using HeapRoots.
There are several ways to trigger a heap dump in the IBM JVM. In the Application Developer environment, the heapdump is generated automatically when an OutOfMemory error or heap exhaustion situation occurs.
But application developers should not defer debugging the memory leaks until an OutOfMemory error happens. Fortunately, there are two other ways to trigger the Heapdump explicitly. The first one is sending a specific signal to the Application Server JVM process. On the Windows platform, this signal is SIGINT. Typing Ctrl+Break
is the common way to send this signal to the process started from a command line window. But in the Application Developer environment, it is
not an option because there is no command line window associated with the embedded Application Server process. You would have to find a program that can generate the SIGINT signal to Windows processes, or write such a program by yourself. The second way to trigger the Heapdump is inserting a
HeapDump() method within the application code. This is the recommended approach. It is not only simple to use but also provides the option to dump the heap at a specific point in the application.
Prerequisites for explicitly generating a heapdump
To explicitly generate a heapdump, activate the Heapdump utility before starting the JVM process by setting the environment variable
IBM_HEAPDUMP to true for the JVM process. For JDK releases later than JDK 1.3.1, SR3,
IBM_HEAPDUMP may be set to any value. There are two alternatives to set
IBM_HEAPDUMP for the Application Server JVM process in Application Developer:
Specify the environment variable IBM_HEAPDUMP in a command line window and run Application Developer from there:
- Open a command line window.
- Set the environment variable from the command line:
SET IBM_HEAPDUMP=true. - Start Application Developer from the command line window by running EXE file wsappdev.exe.
For example,
C:\Program Files\IBM\WebSphere Studio\Application Developer\v5.1.2\wsappdev.exe.
Set IBM_HEAPDUMP as a Windows system environment variable:
- Right click My Computer icon from Desktop.
- Select Properties in the pop-up menu.
- Select Advanced tab in the pop-up System Properties window.
- Click Environment Variables.
- Click New in System Variables panel.
- In the pop-up window, specify
IBM_HEAPDUMPfor Variable Name andtruefor Variable value. - Click OK for all the pop-up windows to save the new environment variable setting.
Tip: Do not specify the environment variable IBM_HEAPDUMP=true in the WebSphere Administrative Console of the
WebSphere Test Environment. It will not work because the setting will not be picked up when the server starts. This is not the case in the standalone
Application Server environment. If IBM_HEAPDUMP=true is set in WebSphere Administrative Console by selecting
Servers => Application Servers => server_name => Process Definition => Environment Entries, then
Heapdump will be enabled in the typical Application Server environment.
Sample application for frequently used object leak
Listing 3 shows the sample code to demonstrate the frequently used object leak and how the
HeapDump() method is used to generate the heapdump:
Listing 3. frequently used object leak sample code
public class MemLeakServlet2 extends HttpServlet {
String[][] leakArray;
public void init() throws ServletException {
super.init();
leakArray = new String [1000][1000];
}
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
for (int i = 0; i<1000; i++)
for (int j= 0; j<1000; j++)
leakArray [i][j] = new String("abcdefghijklmnopqrstuvwsxyz " +
"abcdefghijklmnopqrstuvwsxyz abcdefghijklmnopqrstuvwsxyz " +
"abcdefghijklmnopqrstuvwsxyz abcdefghijklmnopqrstuvwsxyz" );
Dump.HeapDump();
try
{ resp.getWriter().println("The MemLeakServlet2 has been invoked."); }
catch(Exception e)
{ System.out.println(e.toString()); }
}
}
|
This second example simulates a frequently used object leak. It is similar to the first example. The major difference
is that the rarely used object MemLeakClass is removed and the only leaked object is String, which means that Application Developer
Profiler will show that String is the only leaked object. It can be difficult to find the leak in the source code because String is used in many places in a typical J2EE application. Heapdump and HeapRoots are needed to solve the puzzle. Another difference from the first sample application is that
Dump.HeapDump() is added to trigger the Heapdump.
This second sample application is also in memLeakApp.ear.
To run it, start the server in the normal mode in Application Developer and access
welcome2.jsp from a Web browser on the local machine: http://localhost:9080/memLeakWeb/welcome2.jsp.
Then click Invoke servlet to run the servlet, just like running the first sample application.
After invoking the servlet, the heapdump is generated by the method Dump.HeapDump() . You may find the heapdump
file in the current working directory of the Application Server JVM process. For example, if Application Developer is started from the Start menu, the current working directory for the Application Server JVM process is where wsappdev.exe resides. In our test environment, for instance, it is
C:\Program Files\IBM\WebSphere Studio\Application Developer\v5.1.2\. The name of the heapdump file is formatted as
heapdump.date.time.id.txt, such as heapdump.20040831.182458.2332.txt. The console view of the Server perspective in Application Developer shows a message similar to the one below, indicating the name and the location of the heapdump file:
JVMDG315: JVM Requesting Heap dump file ...........JVMDG318: Heap dump file written to C:\Program Files\IBM\WebSphere Studio\Application Developer\v5.1.2\heapdump.20040831.182458.2332.txt |
After the heapdump is generated, use HeapRoots to analyze it and find out which object refers to a large chunk of other objects that can't be released by the JVM garbage collector. Usually, the objects with a large subtree size are the targets of the investigation.
Download HeapRoots from the HeapRoots Web site (free
registration required). It contains HeapRoots documentation and the HeapRoots JAR file HR205.jar. Unzip the downloaded zip
file in a directory such as C:\workspace. To simplify the commands used here, put the generated heapdump file in the same directory.
To invoke HeapRoots and dump the result to a text file:
- Change to the directory where HeapRoots JAR file and heapdump file reside:
cd C:\workspace - Load the heapdump file with HeapRoots:
C:\Program Files\IBM\WebSphere Studio\Application Developer\v5.1.2\runtimes\base_v51\java\bin\java.exe" -Xms500M -jar HR205.jar heapdump.20040831.182458.2332
In above command,
heapdump.20040831.182458.2332is the name of the heapdump file. Thejava.exeis the one shipped with WTE. The JVM option-Xms500Mis used to increase the initial heap size of the JVM running HeapRoots to 500 MB. For a very large Heapdump on the order of 1 GB, increase the value of this parameter accordingly. - Run HeapRoots dump command from the HeapRoots prompt to process the heapdump and output the result to a text file:
d > C:\workspace\heapAnalysis.txt
In above command, d is the HeapRoots dump command. The output of the dump is redirected to the fileC:\workspace\heapAnalysis.txt.
In Figure 5, the command line window shows some of the HeapRoots output when HeapRoots is invoked and the heapdump file is loaded. The output shows the information getting from the heapdump, such as the number of objects and the number of object references recorded in the heapdump. The size of memory used by HeapRoots is listed here as well. It also shows that the HeapRoots dump command is issued from the HeapRoots command prompt.
Figure 5. HeapRoots output and the dump command issued

After issuing the dump command, HeapRoots writes more output to the console window and asks you to enter three parameters for the dump command: total-size threshold, max depth, and dump root address. See the following list for the values specified for these parameters.
- Total-size threshold
- Use default value of 1MB by pressing the Enter key at the prompt, which means that the object is filtered out if the total size of this object's subtree is smaller than 1 MB.
- Max depth
- Set it to 100 by entering the number 100 and pressing Enter. It tells the HeapRoots dump command that the maximum depth (maximum length of the object reference chain) in the tree is 100.
- Dump root address
- Use the default value that includes all root objects in the heap. Simply press Enter.
Figure 6 shows the HeapRoots dump command console output and its parameter values specified from the command line window:
Figure 6. HeapRoots dump command output and its parameter values

The output of HeapRoots organizes the objects into indented trees. The root of a tree is a root object in the heap. The objects referenced by the root object are the children of the root object. The objects referenced by these children are the grandchildren of the root object, and so on. For detailed information, refer to the HeapRoots documentation.
Using Application Developer Profiler or the HeapRoots command tc (Refer to the HeapRoots document for this
command's usage), it is easy to discover that String is the leaked object in this sample application. To determine the
location of the memory leak where the String is used, open the output file heapAnalysis.txt with a text editor and search
for String. The result is strikingly simple in this case as there is only one String-related item in the file:
the String array defined in MemLeakServlet2. Here is the relevant part of the output:
<92> [36,020,424] 0x19abef40 [64] com/ibm/ws/webcontainer/servlet/StrictServletInstance
<93> [36,020,328] 0x19abf290 [24] memleak/MemLeakServlet2
<94> [36,020,304] 0x19ace850 [4,016] array of [Ljava/lang/String
- 1000 children of 0x19ace850 filtered.
- 1 child of 0x19abf290 filtered.
- 6 children of 0x19abef40 filtered.
- 7 children of 0x19abefd8 filtered.
- 2 children of 0x19ac7a30 filtered.
|
The data format for each object in the output of HeapRoots dump command is:
<depth> [total size] address [object size] class
- Information on the children being filtered out.
|
The depth in angle brackets <> is the depth of the object in the tree. In this example, the depth of the String array is 94, which means the String array is the 94th generation of the root object. That is, the length of the reference chain from the root object to the String array is 94. The total size in the first square brackets [] is the size of the object's subtree in bytes, which includes the size of the objects directly or indirectly referenced by this object. The address is the hexadecimal memory address of the object in the Java heap. The object size is the actual size of the object in bytes. After that, it indicates the Java class of the object. If there are additional lines for this object, they are used to list its children being filtered out.
Based on the above information, you know that the object reference chain pointing to the array of the String is
StrictServletInstance => MemLeakServlet2 => array of String, and that the String array has a thousand children, which
consume 36 MB of memory. This information tells you that the simulated String object leak occurs in the MemLeakServlet2 object.
There are several issues to be aware of when using HeapRoots.
- As of Nov. 2004, the HeapRoots
HR205.jarfile downloaded from the HeapRoots Web site sometimes throwsjava.lang.NumberFormatExceptionif the heapdump file is generated by a 1.4.2 JDK. This is a known issue. - The setting of max depth of the HeapRoots output trees should be large enough to reveal the leaked objects being referred to. In our example, it is 100. To solve the memory leak in a typical J2EE application, you may need to set it to a much larger number.
- Locate the leaked object based on the total size of the object's subtree. If an object's subtree, but none of its children's subtrees, consumes a large amount of
memory, this object is the parent of the leaked object. In the above examples, this parent object is
MemLeakServletorMemLeakServlet2. You can find the leaked object inside this parent object. - Use the JVM option
-verbosegcto turn on JVM verbose garbage collection if you suspect there are extensive garbage collection activities. This situation often leads to very large and deep object reference trees in the HeapRoots output, which are more time-consuming and difficult to analyze. Try to avoid this by dumping the Java heap before it occurs.
This article showed you how to identify Java memory leak problems using the IBM tools Application Developer Profiler, JDK Heapdump, and HeapRoots. It illustrated how to approach an application memory leak problem in the Application Developer environment and how to efficiently diagnose the problem with these tools. It then used examples to show you how to set up, configure, and use these tools to solve simple and more complex memory leak problems.
The authors would like to thank Vikram Desai and Jiawan Chen of IBM for reviewing this article.
| Name | Size | Download method |
|---|---|---|
| memLeakApp.zip | 7 KB | FTP |
Information about download methods
-
Diagnostics Guide, IBM Developer Kit and Runtime Environment, Java2 Technology Edition, Version 1.4.1, Service Refresh 1.
More information about the IBM JDK Heapdump utility shipped with IBM JDK 1.4.1.
- IBM JVM Diagnostics documentation.
Diagnostics Guide for all supported IBM JDK versions.
- HeapRoots
Download and learn more about HeapRoots from IBM alphaWorks.
- JProbe Suite and Borland Optimizeit Enterprise Suite.
Additional third-party profiling tools, see
- developerWorks WebSphere Studio zone.
Access to WebSphere Studio how-to articles, downloads, tutorials, education, product information, and more.
- Trial downloads for WebSphere Studio.
No-charge trial downloads for the latest WebSphere Studio products.
- Trial downloads for IBM software products.
No-charge trial downloads for selected IBM DB2, Lotus, Rational, Tivoli, and WebSphere products.
- Browse for books on these and other technical topics.
- WebSphere forums.
Product-specific forums where you can ask questions and share your opinions with other WebSphere users.
- developerWorks blogs. Ongoing, free-form columns by software experts, with space for you
to add your comments. Check out Grady Booch's blog on Software architecture and engineering.
Jiwu Tao is a software engineer working at IBM WebSphere Competency Center, Pittsburgh, PA. He is a certified System Expert on WebSphere Application Server. Prior to this, he worked with WebSphere Application Server development team and was a key developer in WebSphere Application Server EJB caching research project. He holds two Master degrees in Information Science and Electrical Engineering. Before joining IBM, He taught in universities and published several articles in the field of computer science. You can reach Jiwu at jiwu2@us.ibm.com
Priamo Persichetti works in the WebSphere Competency Center, Pittsburgh Lab, Pittsburgh, PA. He is a Certified System Administrator/Expert for WebSphere Application Server V5.0 and 4.0. Prior to his current position, he worked on IBM's electronic software distribution tool (ISSI) as part of the packaging team and IBM's Edge Server product. He has a Master's degree in Information Science. You can reach Priamo at priamop@us.ibm.com




