Unit test for memory leak

Tracking down memory leaks can be hard – so it would good thing if you can make the process a bit easier, and once you’ve found it, you can make sure that it never ever occurs again.

Fortunately, as with many other bugs, unit tests might be an option – even memory leaks can be exercised via unittests:

  • set up your scenario and create a weak reference to the object that is leaked
  • force the GC
  • check that the weak reference is empty

Basically, you set up a weak reference to the object (which can be a node in a whole object graph that should be collected) which should be eaten by the garbage collector.

Afterwards, when you expect that the object should not be referenced any more, you need to force the runtime to run garbage collection. This can heuristically be done by calling (System.gc() in Java, or GC.Collect in C#). As garbage collection isn’t entirely deterministic, it also helps to allocate some bigger chunk of memory to kick the GC into life.

Then the weak reference should be empty. Otherwise, you can expect that it is still referenced somewhere.

public class MemoryLeakTest extends TestCase {

//this test succeeds - the object under test is GC'ed
public void testMemoryLeak() {
	WeakReference<byte[]> reference = new WeakReference<byte[]>(makeObjectUnderTest());
	
	forceGc();
	
	Assert.assertNull(reference.get());
}
	
//this test fails - the object under test is kept alive by the local variable
public void testMemoryLeakFailure() {
	byte[] keepItAlive = makeObjectUnderTest();
	WeakReference<byte[]> reference = new WeakReference<byte[]>(keepItAlive);
	
	forceGc();
	
	Assert.assertNull(reference.get());
}

private void forceGc() {
	//allocate quite some memory to make sure that the GC runs
	byte[] bigChunkOfMemory = new byte[400000000];
	System.gc();
}

private byte[] makeObjectUnderTest() {
	return new byte[100];
}
}
This entry was posted in Software. Bookmark the permalink.