Skip to main content

Preventing Memory Leaks in a Java Application with Rational Purify: A Case Study

Sanjay Gupta, Architect, Talent Transformation, Wipro Technologies
Dr. Sanjay Gupta received a Ph.D. in metallurgical engineering and materials science from the Indian Institute of Technology in Bombay, India, and worked as a research associate for four years in the Department of Physics there. He works now as an Architect in Talent Transformation for Wipro Technologies in India. A Sun-certified Java programmer and Sun Certified Trainer, he's been teaching Java since 2000. He has published research papers in various international journals and presented his research findings at many international and national conferences. His current areas of research, study, and knowledge dissemination are Java, Swings, J2EE technology, magnetic materials and high-temperature superconductivity, and tools like Rational Purify, Rational PureCoverage, and Rational Robot.

Summary:  Memory management needs to be attended to in Java applications despite the presence of the garbage collector. Learn how one developer used heap data captured in Rational Purify to find and correct the causes of memory leaks in a Java application.

Date:  04 Dec 2003
Level:  Introductory
Activity:  507 views

Since Java garbage collection isn't perfect, memory management is an important point of consideration in Java programming, as pointed out by Goran Begic in "Memory Profiling in Java" and Jim Patrick in "Handling Memory Leaks in Java Programs." In this article, I'll show how we at Wipro Technologies detected and corrected memory leaks in a Java application using the Rational Purify® for Java system testing tool, as suggested in Begic's article. I hope it will give you some idea of how this tool can be deployed and the process required to successfully remove a memory leak.

Determining Heap Usage and Memory Leakage

Purify has several options for controlling what information is actually recorded during a debugging session. After some experimentation, we decided that the most efficient way to get the required information about a memory leak is to concentrate on the captured heap data. Purify provides a view that shows the amount of heap memory in use over time as the Java application is running. The Purify GUI also provides these toolbar buttons:

  • Garbage-collect -- to force the JVM to perform garbage collection when desired -- Garbage-collect -- to force the JVM to perform garbage collection when desired
  • Snapshot memory profile data -- to record the data at a particular point -- Snapshot memory profile data -- to record the data at a particular point

These capabilities turned out to be very useful when we were trying to see if a given instance of a class would be garbage-collected when it was no longer needed by the Java application. Figure 1 is a heap usage chart showing the amount of heap storage in use by our Java application over time. In the chart, the blue area indicates the amount of heap space that's been allocated for the particular screen.


Figure 1: Memory In Use profile data for our Java application
Memory In Use profile data for our Java application

After we started running our Java application and it reached a stable point, we forced the garbage collector to run, which is indicated by the sudden drop in the blue area of the Memory In Use profile. Red dots on the profile indicate the garbage collection points. Next we opened and closed one particular screen of our application, played back one test scenario, and invoked the garbage collector, followed by capturing snapshot memory profile data. The fact that the amount of memory indicated by the blue area after each checkpoint is greater than the amount before the checkpoint indicated to us that a memory leak was likely. We estimated the amount of memory leakage by looking at the difference in the values of memory at the y-axis between the second and third snapshot points in Figure 1. For more detailed calculations, we used the more advanced features in Rational Purify.

We took this approach because when we first invoke a Java application, which is a combination of various screens and screen components, the components are created and lie on the heap. When we close the screens, the components go back to the component cache (a Java class that has a number of required frequently used components) and the screens go back to the screen cache (a Java class that contains some GUI properties of the screen). When we invoke the application again, the objects of the various components aren't created from the base class but come directly from the component cache. Hence, the comparison between the second and third snapshots gives us an approximate idea of the amount of memory leakage going on in the application.

Getting Information at the Method Level

To get exact information at the method level, which is responsible for memory leaks, we used the Compare Runs tool to compare the data from the second and third snapshots. (The Compare Runs tool will display only the memory used in between two snapshots.) We saved the results as pmy and also as txt files. We opened the txt file in Microsoft Excel and filtered the data to remove the memory occupied by the Swings components or by the garbage collector. In Rational Purify we used Filter Manager. The call graph resulting from the comparison is shown in Figure 2.


Figure 2: Memory call graph from the Compare Runs measurement
Memory call graph from the Compare Runs measurement

The call graph in Figure 2 displays the chain of methods called between the two snapshots. This figure shows only methods with significant memory usage; other methods can be added to the report by extending the view. The highlighted chain of calls points to the method that used most of the memory during the run (highlighted in blue). This method is the first candidate for detailed analysis.

Figure 3, which gives a close look at the method list of the compared runs, confirms the obvious leak.


Figure 3: List of methods invoked in between the two snapshots
List of methods invoked in between the two snapshots

We added the column entitled "Method bytes allocated (diff)" to get the overall picture of the memory leak in a particular screen. Not all available columns are displayed by default. New ones can be selected from the pop-up menu when right-clicking on the Method List report. To our surprise, many times we got a negative number as the sum of these values. This result means that the memory allocated in these methods was released in between the snapshots -- that is, that the garbage collector was able to release the objects from these methods. In the expanded call graph these methods are marked in green.

Modifying Our Application

We analyzed all the screens through Purify and on the basis of the results, we made these modifications to our application:

  • Removed all listeners from the destroy method of the particular screen class.
  • Nullified all the components, events, variables, and renderers used in the screen in the destroy method of that screen class.
  • Removed all the creation of new instance variables at the class level.
  • Added a method in the event classes that nullifies all the variables / data objects / data transfer objects used in the event and called them at the time of window close before calling the destroy method.
  • Avoided using too many Jpanels; instead we can reuse the already created JPanel by changing its properties if needed.
  • Used the dispose method in the destroy of the screen classes. It releases all of the native screen resources used by the window, its subcomponents, and all of its owned children.

We then tested the application again with Purify. To our great satisfaction, we found that the amount of memory leakage was reduced by 90-95%.

Conclusion

Memory management needs to be attended to in Java applications despite the presence of the garbage collector. I've shown you how we used heap data captured in Rational Purify to find and correct the causes of memory leaks in our Java application. This can be a tedious process, even with a debugging tool like Purify, but the alternative is to watch program performance degrade over time as memory leaks take their toll.


Resources

About the author

Dr. Sanjay Gupta received a Ph.D. in metallurgical engineering and materials science from the Indian Institute of Technology in Bombay, India, and worked as a research associate for four years in the Department of Physics there. He works now as an Architect in Talent Transformation for Wipro Technologies in India. A Sun-certified Java programmer and Sun Certified Trainer, he's been teaching Java since 2000. He has published research papers in various international journals and presented his research findings at many international and national conferences. His current areas of research, study, and knowledge dissemination are Java, Swings, J2EE technology, magnetic materials and high-temperature superconductivity, and tools like Rational Purify, Rational PureCoverage, and Rational Robot.

Comments (Undergoing maintenance)



Trademarks  |  My developerWorks terms and conditions

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Rational
ArticleID=1499
ArticleTitle=Preventing Memory Leaks in a Java Application with Rational Purify: A Case Study
publish-date=12042003
author1-email=
author1-email-cc=

My developerWorks community

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere).

My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Rate a product. Write a review.

Special offers