Understanding Strong, Soft, Weak and Phantom Reference of Java

There are 3 rarely used Java Classes SoftReference, WeakReference and PhantomReference which are extended from the abstract Class java.lang.ref.Reference. Honestly, I didn’t ever use them either, I just find them every interesting, because they might help me improving some performance issues of my program in some extreme cases.

Strong Reference

I think most of the Java developers are familiar with the Strong Reference concept: it says actually if a new object is created and assigned to a variable, the variable is then referenced to the new object, and this object has a strong reference. A strong reference object will never be collected by the GC.

Weak Reference

But if the ref is reassigned by other object or simply by null, the old Object will be eligible to the GC. It’s not necessary for the GC to collect it at once, when will it be collected depends on the algorithm of the JVM, so “at the next GC cycle” could be a nice expression. At this time the status of the new object is almost equal to a WeakReference, the difference is that without the WeakReference, it’s difficult to find the free state Object (object without any variable points to it) back.

WeakHashMap

For example, the WeakHashMap uses a WeakReference as key. The GC will only collect the entry as long as there is no strong reference between the key and value.

String a = new String("a");
String b = new String("b"); 

Map map = new HashMap();
map.put(a, "a");
map.put(b, "b"); 

Map weakMap = new WeakHashMap();
weakMap.put(a, "a");
weakMap.put(b, "b");  

map.remove(a);

// you know what I mean, no need to call it in your program
System.gc();

/* because the a hasn't strong reference any more,
   the key in the weakMap will be collected */
boolean willBeFalse = weakMap.containsKey(a);

a = null;
b = null;

// because the b still has strong reference in the map
boolean willBeTrue = weakMap.containsKey(b);

Soft Reference

The SoftReference is a bit stronger than WeakReference, because it will only be collected when the GC thinks the available memory is too low, thus it is also ideal to be used in a Cache implementation.

// Strong reference
Object ref = new Object(); 

/* It's eligible to the GC when ref is reassigned,
   It'll be collected at the next GC cycle */
WeakReference weakRef = new WeakReference(ref);

/* It's eligible to the GC when ref is reassigned,
   It'll be collected when memory too low */
SoftReference softRef = new SoftReference(ref);

// reassigned
ref = null;

/* return null if the free state object is already collected by the GC,
   else we get the reference to the object back */
Object ref = weakRef.get();

/* return null if the free state object is already collected by the GC,
   else we get the reference to the object back */
Object ref = softRef.get();

Phantom Reference

The Phantom Reference is quite different, its get() method will always return null. However it has a second parameter ReferenceQueue in its Constructor, will keep the reference in the Queue. It’s often used to monitor object creation and destruction, allow you to determine exactly when an object was removed from memory. You can also see this answer

Object ref = new Object();
ReferenceQueue refQueue = new ReferenceQueue();
PhantomReference phantomRef = new PhantomReference(ref,refQueue);

Object alwaysNull = phantomRef.get();
// reference in the Queue now
boolean willBeTrue = phantomRef.isEnqueued();

Reference polled = refQueue.poll();
// reference in the Queue polled out
Object notNull = polled;

Comparison of the References

Following comparison table gives an overview of the Hard, Soft, Weak and Phantom References: (table originally from here)

Strong vs Soft vs Weak vs Phantom References
Type Purpose Use When GCed Implementing Class
Strong Reference An ordinary reference. Keeps objects alive as long as they are referenced normal reference Any object not pointed to can be reclaimed. default
Soft Reference Keeps objects alive when there’s enough memory such as memory sensitive caches, in case clients start asking for them again by key After a first gc pass, the JVM decides it still needs to reclaim more space. java.lang.ref.SoftReference
Weak Reference Keeps objects alive only while they’re in use by clients. Containers that automatically delete objects no longer in use After gc determines the object is only weakly reachable java.lang.ref.WeakReference
java.util.WeakHashMap
Phantom Reference Lets you clean up after finalization but before the space is reclaimed Special clean up processing After finalization. java.lang.ref.PhantomReference

Most of the programs will not use the 3 References that are introduced here, but it’s nice to know there are such interesting classes to use and they might also help you understand GC and JVM better.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.