Amit kumar
Amit kumar

Reputation: 2714

Why Java has 4 different types of references?

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 ?

Upvotes: 5

Views: 1402

Answers (3)

Borislav Stoilov
Borislav Stoilov

Reputation: 3697

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

Upvotes: 0

Eugene
Eugene

Reputation: 120978

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.

Upvotes: 2

GhostCat
GhostCat

Reputation: 140573

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.

Upvotes: 2

Related Questions