This product is provided "as-is," without any expressed or implied warranties or support by BEA Systems, Inc. This product, which may or may not become an officially supported product from BEA Systems, may contain errors and/or inaccuracies. Use of this product is left solely upon the discretion of the user without any endorsement from BEA Systems. The Memory Leak Detector functionality may or may not be available in future BEA JRockit versions. Questions and problems may be reported via online BEA JRockit newsgroups at http://newsgroups.bea.com.
The BEA JRockit Memory Leak Detector is a tool to detect memory leaks within Java applications running on BEA JRockit. A memory leak means application code holding on to memory which is not actually used by the application any more. The BEA JRockit Memory Leak Detector is a real-time profiling tool that gives information about what type of objects are allocated, how many, of what size and how they relate to each other. Unlike other similar tools, there is no need to create full heap dumps to be analyzed at a later stage. The data presented is fetched directly from the running JVM and the JVM can continue to run with a relatively small overhead. When the analysis is done, the tool can be disconnected, and the JVM will run at full speed again. This makes the tool viable for use in a production type environment.
The purpose of this tool is to display memory leaking object types and provide help to track the source of the problem. Another purpose of this tool is to help the developer by increased understanding and knowledge to avoid similar programming errors in future projects.
This section describes the BEA JRockit Memory Leak Detector (from now on referred to as Memory Leak Detector) and how to use it to detect memory leaks. It includes information on the following subjects:
-Xmanagementoption to the command line.
Figure 5-1 displays the content of this tab.
In Table 5-1 you can find detailed explanations of what each column stands for. When starting the memory leak data collection you also get a message from JRockit that the "ManagementServer started trend analysis".
Trend analysis means to observe continuously updated object type related information and try to discover object types with suspicious memory growth. These object types should then be studied in the next phase of the memory leak detection process. The information in the trend analysis table will be updated each time a garbage collection is performed.
Studying object type relations means repeatedly following reference paths between object types, i.e. classes. The goal is to find interesting connections between growing object types and what types of objects points to them. Finding the object type guilty of the unusual memory growth will lead to the third and final phase of the memory leak detection process.
Instance investigation consists of finding an instance of abnormal memory size or holding an abnormal amount of references and then inspect that instance. When inspecting an instance, values will be displayed, e.g. field names, field types, and field values. These values will hopefully lead you to the correct place for the error in the application code, i.e. where that particular instance of that particular object type is allocated, modified, or removed—depending on what the situation implies. Minimizing the problem areas to the ones connected to the suspected instance will most likely lead you on the right track to finding the actual problem causing the memory leak and fix it.
To analyze an application you need to start the Memory Leak Detector (see Starting the Memory Leak Detector).
The growth values marked in red show the object types that grow more than 100 bytes/sec. The areas marked in yellow indicate object types that grow between 10 and 100 bytes/sec. Object types that grow less than that are white.
A menu appears, see Figure 5-3.
The Referring Types Window appears that displays a list of the object types pointing to that particular type of object, see Figure 5-4.
In the new Referring Instances Window that appears, see Figure 5-7, you can see static fields and how many thread roots are referring to the instance in question.
When inspecting an instance you get all necessary data to hopefully track the particular instance in the application code. You get the field names, their types, and their values. Trying to map these values to the code will help you discover the source of the memory leak.
In some cases the lists that is displayed may be very long. In those cases you will be notified and informed about the consequences of displaying such a list, see Figure 5-9.
Below follows an example of how to find a memory leak by narrowing down the search space. Once the search space is narrowed down, you will hopefully find the exact problem area and then be able to solve the problem by changing you application.
After starting the Memory Leak Detector, choose to investigate the object type that grows the most and which is not expected to grow, considering the design and the purpose of the application. In this example it turns out to be the DemoObject object type (Figure 5-10). Select the row corresponding to the suspected object type, right-click on it and choose the menu option Show types pointing to this type.
A Referring Types Window (Figure 5-4) appears displaying the one object type pointing to the DemoObject. It turns out to be HashTable$Entry. To pursue this suspected memory leak path, select the corresponding row, right-click on the selection, and choose Show types pointing to this type once again.
In the new Referring Types Window that appears, note the two object types pointing to the previous object type. One is HashTable$Entry[ ] and the other is HashTable$Entry. Notice that the number of references from the HashTable$Entry[ ] type is much larger than expected and choose to investigate this array type further. Select the row corresponding to the array type, right-click the selection, and choose Show types pointing to this type. By selecting this option, you find that the object type HashTable is pointing to the array in the new Referring Types Window that appeared.
Return to the previous window and select the suspected array type again. Right-click on the selection, but this time choose Show largest arrays of this type. A Largest Array Window (Figure 5-6) appears with a list of the ten largest instances of this array, with the largest listed on top. This information tells you that it is one single array instance being responsible for the large memory occupation.
Instead of choosing the other alternative: Show instances of this type pointing to <TYPE>, where TYPE in this case is HashTable$Entry the new window that appears presents a warning for a large amount of references maybe causing the connection to the JRockit process to be lost. This means that the HashTable$Entry[ ] consumes unexpected amounts of memory and is holding on to an enormous amount of references to HashTable$Entry.
Return to the Largest Array Window. Select and right-click the suspected alternative, i.e. the instance occupying the largest amount of memory. Select Show instances pointing to this array. A Referring Instances Window (Figure 5-7) appears with a list of instances pointing to the array. It is a HashTable instance (Figure 5-11).
The Inspection Window (Figure 5-8) appears. In that window you can see different field names, their types, and their values (Figure 5-12). Pretty soon you will probably be able to map these fields and values to a certain point in the application code.
From this example, you can draw the conclusion that somewhere you add HashTable$Entry instances into the HashTable$Entry[ ] which is kept alive by a HashTable. You can also read that your application never seems to remove them, since the memory occupied by these type of objects is continuously growing. To confirm the beliefs, investigate the code thoroughly at the place where the instance field info has taken you.
The source of the confirmed memory leak turned out to be in a place in the code where, after HashTable$Entry objects are added to the HashTable$Entry[ ] in a HashTable. The application removed all of the HashTabe$Entry objects except one; it missed the last instance due to an off-by-one error (a very common error causing memory leaks of this sort).
The Memory Leak Detector provides an easy way to capture information about object type allocation statistics. It is designed to help developers to easier find memory leaks and to better understand critical points of program engineering.
If you have any suggestions relevant for this purpose on how to improve this tool or information on how it is most commonly used in development environments, we would be grateful to receive your input. This information would contribute to our understanding on how to best further improve this tool in the future.
The feedback will be considered by the development team designing the Memory Leak Detector. We will look at collected ideas and improve the tools of BEA JRockit to make them even easier to use. Our goal with the development of this tool is to simplify the difficult task of finding memory leaks in the future and help the developer work more efficiently.
BEA JRockit is already providing a lot of appreciated manageability tools, and to stay appreciated and to keep a close dialogue with developers using Java Runtime Environments, BEA Systems is always trying to find ways to improve BEA JRockit. This is one of the ways.
During the first phase of the memory leak detection process the data presented is continuously updated; however, the overhead during this phase is very small. During the second and third phase the only overhead that will be caused is some additional garbage collections which in most cases is negligible. Overall, there is practically no overhead and it should not affect the speed or results of your application.
Sometimes static fields and the number of thread roots are not correctly displayed in the window displaying instances referring to an other instance. This can be helped by starting the memory leak detection process one again (i.e. unfreezing and freezing the memory leak system). However, if there is data displayed, it is the correct values.