Tuesday 16 December 2008

Java Garbage Collection for String literals

Tonight I had a ponder about Javas garbage collection mechanism and what would make an object held by a WeakReference be garbage collected. The answer was quite simple, create a instance of a variable, create a WeakReference for it, null the instance and call System.gc(). I'm guessing that the instance would be garbage collected on the next natural sweep but because I was using a unit test I needed it to be done straight away.

However, garbage collection on string literals is far more interesting. See the unit tests.

import static org.junit.Assert.*;

import java.lang.ref.WeakReference;

import org.junit.Test;

public class ReferenceTest
{
@Test
public void testWeakReference()
{
Object reference = new Object();

WeakReference<Object> weakRef =
new WeakReference<Object>(reference);

assertNotNull(reference);

reference = null;

// reference will not be null
// without garbage collection here
System.gc();

assertNull(weakRef.get());
}

@Test
public void testWeakStringReference()
{
String reference = new String();

WeakReference<String> weakRef =
new WeakReference<String>(reference);

assertNotNull(reference);

reference = null;

// reference will not be null
// without garbage collection here
System.gc();

assertNull(weakRef.get());
}

@Test
public void testWeakStringLiteralReference()
{
String reference = "my reference";

WeakReference<String> weakRef =
new WeakReference<String>(reference);

assertNotNull(reference);

reference = null;

// does not matter if garbage collection
// is here or not but lets do it anyway
System.gc();

// !!!
assertNotNull(weakRef.get());
}
}





All of these tests pass. Notice the last test, even after the string instance has been nulled the WeakReference still has a not null value. After a bit of googling I found that string literals are referenced from Javas 'String Literal Pool' which is a cache for string literals so is not eligible for garbage collection!