Garbage Collection, Reference types and Reachability – Strong, Soft, Weak, Phantom, Unreachable
The Java Virtual Machine has 5 different levels of reachability for an object.
- An object is strongly reachable if it can be reached by some thread without traversing any reference objects. A newly-created object is strongly reachable by the thread that created it.
This is the reference you know about and use all the time. Any object that is reachable by a strong reference (from a live thread) will not be collected by the GC.
- An object is softly reachable if it is not strongly reachable but can be reached by traversing a soft reference.
The garbage collector will collect softly reachable objects only if it actually requires more memory. Before it does a GC it is guaranteed to collect softly reachable objects.
So it is possible to write code on the lines of – “Hey, I do want this data to be kept in memory. But in case the JVM starts running out of memory, go ahead and collect it and null out the referent. I’ll handle it in my code.” The exact algorithm that is used to determine whether a SoftReference should be cleared out is JVM vendor dependent. It tends to be a function of how often and how long ago the reference was last used to reach the referent.
The semantics of a SoftReference make it possible to make a memory sensitive cache. The gotcha is that the exact behaviour will be JVM dependent. And as with anything else related to garbage collector behaviour, guarantees are few and are vendor dependent. For higher reliability (and many more features) most people tend to use something like Ehcache rather than roll out their own caching logic using SoftReference unless they have a very simple use case. Used in the right situation, they certainly can result in some elegant, simple code.
- An object is weakly reachable if it is neither strongly nor softly reachable but can be reached by traversing a weak reference. When the weak references to a weakly-reachable object are cleared, the object becomes eligible for finalization.
In a nut-shell, a weak reference will not prevent its referent from being collected by the garbage collector. The most common use case of a WeakReference is via a WeakHashMap. It is an easy way to associate data with an object bound to the lifetime of the object. The bound data will stay in the map only while the key is not weakly reachable due to the key being strongly reachable because of reachability via a reference elsewhere in the application. Once all other references in the application are gone, the key becomes weakly reachable and is gone from the map without the user needing to explicitly remove the entry. An elegant way to prevent memory leaks in some cases!
- An object is phantom reachable if it is neither strongly, softly, nor weakly reachable, it has been finalized, and some phantom reference refers to it.
The referent of a PhantomReference can never be retrieved. The get() method on this reference always returns null! So what is the use?
All Reference types allow specifying a ReferenceQueue in the constructor. The semantics of how and when a PhantomReference is enqueued makes it possible to do finalization in a better, less fragile way. More on that in a future blog post perhaps.
- An object is unreachable, and therefore eligible for reclamation, when it is not reachable in any of the above ways.
See also: Package java.lang.ref
Tags: Garbage Collector, GC, Java, JVM