Writing JUnit tests for memory leaks
November 6th, 2007 by Nick
Memory leaks are no fun — to find them, you usually have to do a work flow while using a profiler like YourKit, force garbage collection, capture a memory snapshot, and then manually go through the snapshot looking for objects that you expected to be gone but are still there.Even after you’ve finally fixed the memory leak, how can you make sure that the issue doesn’t resurface later? Every good developer knows that, if you fix a bug, you should probably also have a JUnit test for that bug so that it doesn’t happen again. But how can you test for memory leaks programmatically?Find out after the jump…
How do you check for something that doesn’t exist?
The main challenge with programmatically testing for memory leaks is figuring out how to know whether or not you’re leaking memory. If you want to check to see whether a certain object is still allocated, it seems like you’d have to have a reference to it. However, if you have a reference to it, it’s not going to be garbage collected. But if you don’t have a reference to it, how are you supposed to check whether or not it’s been freed?
The power of weak references
Luckily, Java has just the construct for us: weak references. Weak references — objects of class WeakReference — act as references to an object, but, unlike normal references, they will not prevent the object from being garbage collected. Thus, once an object reaches a state in which it is only referenced by weak references, it will be eligible to be reclaimed by the garbage collector.Weak references can also be associated with a ReferenceQueue, which is a queue that holds WeakReference objects whose status has changed (for WeakReference objects, a status change occurs when the object that it is referring to is no longer reachable by strong references). We are guaranteed that, once an object becomes weakly reachable, it will be enqueued in its associated ReferenceQueue.Note: I am simplifying some things and skipping over other things like soft references and phantom references. For a more detailed explanation of these topics, check out this SDN article and this Java.net blog entry.
Writing the unit test
The properties of WeakReference objects make them perfect to use for tests where we want to see whether or not a certain piece of memory has been freed. The general process works as follows:
- Create an object using a strong reference (assign it to a variable).
- Create a ReferenceQueue object.
- Create a WeakReference that refers to the desired object from step 1 and uses the ReferenceQueue from step 2.
- Do whatever operations are needed to produce the suspected leak.
- Release the known strong reference to your object (set the variable in step 1 to
null). - Force garbage collection. (Technically, we are making a request for garbage collection using System.gc() — there’s no way to actually force it to occur. However, it’s the best we can do, and seems to work sufficiently well). If you’re having trouble with forcing garbage collection, anecdotal evidence seems to indicate that requesting garbage collection at least ten times will guarantee that garbage collection actually happens.
- Check to see if your WeakReference from step 3 has been enqueued. If it has, then it will be freed, and there’s no leak. If it hasn’t, then there’s still a hard reference to it somewhere in your code, which means that it is being leaked.
That’s it! You can now write unit tests that test for memory leaks in your code. This obviously isn’t very effective for leaks that only occur after extensive UI interactions, but we’ve found it extremely useful for testing things such as verifying that our models correctly free all of their child models in the correct manner.
Sample code
Here’s a simple sample unit test that tests to make sure that an object will be freed once its reference is set to null:

