Until today, I wasn't aware of the fact that Java has four main types of references.
Java
uses.GC
reclaims this object’s memory in next run even though there is enough memory.GC
reclaims this object’s memory only when it needs some memory badly.reference queue
.I understood the basic concept and I wrote a small program to understand how each of the reference types work.
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
class User
{
public User info()
{
System.out.println("Info method invoked from User class");
return null;
}
}
public class ReferencesExample
{
public static void main(String[] args)
{
//Strong Reference
User userRefObj = new User();
System.out.println("1 :" + userRefObj.info());
// Weak Reference
WeakReference<User> weakref = new WeakReference<User>(userRefObj.info());
System.out.println("2 : " + weakref);
// Soft Reference
SoftReference<User> softref = new SoftReference<User>(userRefObj.info());
System.out.println("3 : " + softref);
// Phantom Reference
ReferenceQueue<User> refQueueObj = new ReferenceQueue<User>();
PhantomReference<User> phantomRef = new PhantomReference<User>(userRefObj.info(),refQueueObj);
System.out.println("4 : " + phantomRef);
}
}
Output :
1 :null
Info method invoked from User class
Info method invoked from User class
2 : java.lang.ref.WeakReference@15db9742
Info method invoked from User class
3 : java.lang.ref.SoftReference@6d06d69c
Info method invoked from User class
4 : java.lang.ref.PhantomReference@7852e922
Doubt : How do we decide which reference type to use and where exactly to use in a real world scenario ?
It's a complicated answer to provide, especially the "real world" portion. These special references are a (very) sharp tool to use, it should only be touched rarely and with a very good understanding. Your first misconception is that only Phantom References
use a queue
(called ReferenceQueue
). In fact, they all use a queue
. PhantomReference
was a bit of a "weirdo" among these all, mainly because the specification around it has changed from java-8
to java-9
. You can read this answer to get some details (the reasons for keeping the instance alive in java-8
is unknown to this time).
Then the common misconception you get is that "next run", for more details you can take a look here. The notion here of the "second", or "next" is a bit tricky; but the point is that this is non-deterministic.
Providing "real world" examples, comes a bit tricky too. That happens because you rarely use these references directly, they usually come pre-packaged in utilities. For one example, you can take a look of how WeakHashMap works (that directly uses the WeakReference
and ReferenceQueue
under the hood), or event this answer. guava
with its CacheBuilder
used to offer some functionality dealing with SoftReferences
(but not anymore), caffeine still does though.
PhantomReferences
are used internally for Cleaner API
(since java-9
). here is an example that shows its general usage. Without PhantomReferences
, this would not really be possible (at least not that "easy").
To that extent, we use WeakHashMap
in production (so do we use Cleaner API
, but much less). If you really want to learn about them, you need to understand how a garbage collector
works (like, really works), then read their official documentation and try (and ask) multiple things.