Elliott C. Back: Internet & Technology

Java Memory Leaks w/ Finalize Examples

Posted in Code, Java by Elliott Back on February 3rd, 2008.

Most people think Java cannot leak memory, but actually that’s not true. Java, unlike languages such as C or Javascript, can have two kinds of memory leaks:

  • True leaks – unreferenced, unrecoverable segments of memory
  • Soft leaks – memory that could be garbage collected, but is “accidentally” referenced

The first kind of memory leak, the true leak, is common to C. It’s trivially easy to write a C program which leaks memory like a sieve by simple putting a call to malloc(…) inside a tight loop. This creates unbounded amounts of heap memory and eventually runs out of space. Additionally, the memory is lost if you don’t save a pointer to it. However, the same program in Java will not run out of memory:

public class finalizer {
	public static void main(String[] args) {
		while (true) {
			finalizer f = new finalizer();
			System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
		}
	}
}

The output looks similar to this:

15757280 bytes free!
15965176 bytes free!
16274928 bytes free!
16584368 bytes free!
15770768 bytes free!

As you can see, since the object we create are unreferenced, the garbage collector can clean them up. Circular references are also no problem for the Java garbage collector, which uses a generational mark-and-sweep algorithm, as demonstrated by this example:

import java.util.LinkedList;
import java.util.List;

public class finalizer {
	protected Object ref;

	public finalizer(Object ref){
		this.ref = ref;
	}

	public static void main(String[] args) {
		while (true) {
			List x = new LinkedList();

			for (int i = 0; i < 100000; i++) {
				x.add(new finalizer(x));
			}

			x = null;

			System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
		}
	}
}

This creates a linked list in which every element also contains a reference to the list, then blows away the scope of the list entirely by dereferencing x and moving into a new loop scope. This leaves all the elements we just allocated floating in memory and all pointing at each other, but not pointed to by our active memory graph. The output shows that this memory is reclaimed:

12601488 bytes free!
8597784 bytes free!
4584656 bytes free!
12596808 bytes free!

Unfortunately, though, there is a way to create true memory leaks in java, and that is with a poor implementation of the finalize method, which is described in the Java 6 docs as:

The general contract of finalize is that it is invoked if and when the JavaTM virtual machine has determined that there is no longer any means by which this object can be accessed by any thread that has not yet died, except as a result of an action taken by the finalization of some other object or class which is ready to be finalized.

The finalize method exists on every Object and is called by the garbage collector’s thread before it reclaims that memory. So, the simplest thing we can do to prevent the garbage collector from reclaiming it is to yield execution:

public class finalizer {
	@Override
	protected void finalize() throws Throwable {
		while (true) {
			Thread.yield();
		}
	}

	public static void main(String[] args) {
		while (true) {
			for (int i = 0; i < 100000; i++) {
				finalizer f = new finalizer();
			}

			System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
		}
	}
}

This produces a quick memory leak and Out of Memory Exception:

12591736 bytes free!
8599816 bytes free!
4584576 bytes free!
602496 bytes free!
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

Throwing any kind of Exception or Error from finalize() also prevents the garbage collector from reclaiming the memory:

public class finalizer {
	@Override
	protected void finalize() throws Throwable {
		throw new Exception("x");
	}

	public static void main(String[] args) {
		while (true) {
			for (int i = 0; i < 100000; i++)
				new finalizer();

			System.out.println("" + Runtime.getRuntime().freeMemory() + " bytes free!");
		}
	}
}

12380920 bytes free!
8687296 bytes free!
5608880 bytes free!
1796496 bytes free!
Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

Abuse of the Object.finalize(…) contract is the only way I know of in pure Java to create a true memory leak. If you widen the scope to include JNI (Java Native Interface), you can bind to an object which leaks memory in native code, but inside the process space of your Java application.

This entry was posted on Sunday, February 3rd, 2008 at 12:15 pm and is tagged with . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback.

11 Responses to “Java Memory Leaks w/ Finalize Examples”

  1. Richa says:

    Thank you. This was helpful.

  2. Govind says:

    thanks, these is amazing thing but actually in C langugae using of malloc function for creating real time memory heap.

  3. brent says:

    A sure fire to create a memory leak is to use the Applet’s sound class…

  4. Chris says:

    Another static analysis tool for detection of memory leaks in Java is Klocwork Developer for Java. You can try it for free on your code at http://www.klocwork.com/products/developerJava.asp

  5. Tony says:

    Interesting work. Thanks. I found a sure way to cause a memory leak.. don’t close a ResultSet or a Statement, even if they are local vars and the method exits, the dangling ResultSet and/or Statement will hang around. In this case use try-catch-finally and close those two in the finally block. (this is assuming you are using a connection pool and the pool will take care of he Connection. Happy coding…. :)

    • ryan says:

      I am guessing that this ResultSet/Statement issue is because these are actually using the JNI and so the java garbage collector isn’t responsible for cleaning them up.

  6. John Lacey says:

    I’m not buying the argument that throwing an exception leads to a memory leak. I can’t find any reports of a bug on the Sun database. I think the test program is just slowing the finalizer thread down too much. Throwing an exception is expensive, especially compared to allocation of tiny objects. The last example is just a variation on the version that calls Thread.yield. You can accomplish the same thing with Thread.sleep(1) [sic].

    I’ve tried a variation that throws an exception in finalize but sleeps in the main loop to give the finalizer thread time to catch up, and it doesn’t appear to have a memory leak. I also tried allocating a byte array per instance to make a memory leak more clear, and that didn’t cause a problem, either.

  7. victor louis says:

    You can prevent memory leaks by watching for some common problems. Collection classes, such as hash tables 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. . The prevalence of memory leak bugs has led to the development of a number of debugging tools to detect unreachable memory. Coverity Prevent is one of the tool that you can use for fixing these kinds of bugs. Coverity Prevent is also used by the Department of Homeland security to scan many open source projects. You can get more info at http://www.Coverity.com

  8. Maxim Zakharenkov says:

    Hi Eliott,

    Nice article, but the example with throwing exception does not produce a memory leak on my machine with Windows and JDK1.5.0_14. It looks like it is bug on your test environment JVM because it is too simple to solve for
    JVM developers.

    Even more the example with “yeild” worked correctly till the end. This also surprised me:
    617496 bytes free!
    5718936 bytes free!
    1730224 bytes free!
    8264520 bytes free!
    4276944 bytes free!
    17578448 bytes free!
    13581144 bytes free!
    9627928 bytes free!
    5595912 bytes free!
    1603760 bytes free!
    22516464 bytes free!
    18476968 bytes free!
    14455080 bytes free!
    10518848 bytes free!
    6496960 bytes free!
    2475072 bytes free!

    But finally I’ve got memory leak with this program:

    static class Finalizeable {

    // reserve ~10K
    int[] array = new int[1024*10];

    void run() {
    for (int k = 0; k

  9. Finalize is Evil, and if you think you have a good use for it, you’re wrong. Just don’t touch it. Don’t even think about it. Your best-case scenario is that it almost does what you think it does at the cost of drastically slowing down GC and hindering reclaimation. The common scenario is that it fails to accomplish what you want it to accomplish while ruining your performance and (likely) leaking memory.

    Thank you VERY much for posting this. People need to see it.

Leave a Reply

Powered by WP Hashcash