Wednesday, December 19, 2007

Eliminating memory leaks

It is almost impossible to improve the performance of your code if your application is impacted by memory leaks. Memory leaks can be in either Java or native code. In native code, memory leaks are caused by the programmer forgetting to free a memory block. Java memory leaks are often caused by saving an object reference in a class level collection and forgetting to remove it at the proper time. There are also other kinds of problems with managing resources that impact performance, such as not closing JDBC Statements/ResultSets in a finally block (many JDBC drivers store a Statement reference in the Connection object). Fixing memory/resource leaks in the application not only has a great impact on performance but also system stability, as you will consume fewer resources.

There are some great tools in the marketplace that make it easy to find Java memory leaks. There are also tools for finding native memory leaks, but you shouldn’t need them unless your company is writing native code. It should suffice to monitor the memory used at the operating system level over a period of time while the client load test is running. In theory, if the application is repeating the same operations, total process memory should not creep up over time (it should level off). If the total memory of the Java process increases each time the client load test is run, then you probably have a memory leak to track down.

To determine if the memory leak is caused by a Java memory leak, you should monitor the Java memory used. The following code can be used for this purpose in the application:

System.out.println(“Java memory in use = “ + Runtime.getRuntime().totalMemory() –
Runtime.getRuntime().freeMemory());

You would want to view this information after running the client test load. If the Java memory is increasing in proportion to the total process memory increase, then you are probably leaking Java memory. If the Java memory is stabilized but the total process memory is increasing, you are probably leaking native memory. You have to make a judgment call on whether this technique applies to your application. If the application is designed to consume additional memory after each client request, then this technique will not help you determine if you have a memory leak. You will have to use commercially available Java/native memory leak finding tools instead.

Preventing memory leaks

You can prevent memory leaks by watching for some common problems. Collection classes, such as hashtables and vectors, are common places to find the cause of a memory leak. This is particularly true if the class has been declared static and exists for the life of the application.

Another common problem occurs when you register a class as an event listener without bothering to unregister when the class is no longer needed. Also, many times member variables of a class that point to other classes simply need to be set to null at the appropriate time.