5

Until today, I wasn't aware of the fact that Java has four main types of references.

  1. Strong Reference : Default reference type that Java uses.
  2. Weak Reference : If an object has a weak reference then GC reclaims this object’s memory in next run even though there is enough memory.
  3. Soft Reference : If an object has a soft reference, then GC reclaims this object’s memory only when it needs some memory badly.
  4. Phantom Reference : If an object has a phantom reference, then it's eligible for garbage collection. But, before GC, JVM puts the objects which are supposed to be garbage collected in a queue called 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 ?

Amit kumar
  • 2,169
  • 10
  • 25
  • 36
  • 1
    99% of the time you use good old normal strong references and don't bother with the rest. They are really just used in some specialized use cases (such as memory-sensitive caches, which are also really hard to get right). Usually they are hidden inside dedicated libraries that use them. – Joachim Sauer Feb 07 '21 at 09:55
  • Yeah. I understand. But what's the point of having 4 different reference types, when we end up using strong type references most of the time ? – Amit kumar Feb 07 '21 at 10:00
  • 2
    Because, for the other 1%, we need other reference semantics. – Turing85 Feb 07 '21 at 10:13
  • The reference jungle makes sense in an environment where resources are limited. For example Android Applications. – Murat Karagöz Feb 07 '21 at 10:18
  • 2
    Thats like asking why chefs have special knives, well you and me dont need those, but they absolutely do. Also notice that your understanding of those is incorrect, you might want to document yourself more – Eugene Feb 07 '21 at 18:47
  • Thanks @Eugene. This contrast was kind of eye opener to me. Also, It would be really helpful if you could point out where I am going wrong, while trying to understanding the concept. This is new to me and I am unable to figure out. – Amit kumar Feb 07 '21 at 18:54

3 Answers3

2

The factual answer is pretty simple: because strong references alone aren't sufficient. You definitely need some concept of weak references in real world production code.

One could then argue that the other types are simply over engineering. The designers of the language assumed these to be helpful, but besides very obscure situations, they aren't. But note: the corresponding semantics can't be done with normal java code. So this is one of these cases "let's add it to the language in case we ever need it".

But that 2nd paragraph could easily be seen as opinion, not fact.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
2

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
Eugene
  • 117,005
  • 15
  • 201
  • 306
0

There isn't much to add to the existing answers, other than a brief summary

  • Weak references are used (mostly internally) as a temporary cache that gets wiped on the next GC
  • Soft references are very similar to the weak ones, with the only difference being that the GC will collect them only when the memory is low. Soft references will never cause OOE
  • Phantom references are the "new" finalization mechanism and with them, you can execute some logic when the object is collected. Very similar to the (now deprecated) finalize method. PhantomReference.get always gives you null and you can't find the object with them

I tried to gather more information in this article, there are also some real-life example of code

Borislav Stoilov
  • 3,247
  • 2
  • 21
  • 46