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.