What's the difference between SoftReference and WeakReference in Java?

231,756

Solution 1

From Understanding Weak References, by Ethan Nicholas:

Weak references

A weak reference, simply put, is a reference that isn't strong enough to force an object to remain in memory. Weak references allow you to leverage the garbage collector's ability to determine reachability for you, so you don't have to do it yourself. You create a weak reference like this:

WeakReference weakWidget = new WeakReference(widget);

and then elsewhere in the code you can use weakWidget.get() to get the actual Widget object. Of course the weak reference isn't strong enough to prevent garbage collection, so you may find (if there are no strong references to the widget) that weakWidget.get() suddenly starts returning null.

...

Soft references

A soft reference is exactly like a weak reference, except that it is less eager to throw away the object to which it refers. An object which is only weakly reachable (the strongest references to it are WeakReferences) will be discarded at the next garbage collection cycle, but an object which is softly reachable will generally stick around for a while.

SoftReferences aren't required to behave any differently than WeakReferences, but in practice softly reachable objects are generally retained as long as memory is in plentiful supply. This makes them an excellent foundation for a cache, such as the image cache described above, since you can let the garbage collector worry about both how reachable the objects are (a strongly reachable object will never be removed from the cache) and how badly it needs the memory they are consuming.

And Peter Kessler added in a comment:

The Sun JRE does treat SoftReferences differently from WeakReferences. We attempt to hold on to object referenced by a SoftReference if there isn't pressure on the available memory. One detail: the policy for the "-client" and "-server" JRE's are different: the -client JRE tries to keep your footprint small by preferring to clear SoftReferences rather than expand the heap, whereas the -server JRE tries to keep your performance high by preferring to expand the heap (if possible) rather than clear SoftReferences. One size does not fit all.

Solution 2

Weak references are collected eagerly. If GC finds that an object is weakly reachable (reachable only through weak references), it'll clear the weak references to that object immediately. As such, they're good for keeping a reference to an object for which your program also keeps (strongly referenced) "associated information" somewere, like cached reflection information about a class, or a wrapper for an object, etc. Anything that makes no sense to keep after the object it is associated with is GC-ed. When the weak reference gets cleared, it gets enqueued in a reference queue that your code polls somewhere, and it discards the associated objects as well. That is, you keep extra information about an object, but that information is not needed once the object it refers to goes away. Actually, in certain situations you can even subclass WeakReference and keep the associated extra information about the object in the fields of the WeakReference subclass. Another typical use of WeakReference is in conjunction with Maps for keeping canonical instances.

SoftReferences on the other hand are good for caching external, recreatable resources as the GC typically delays clearing them. It is guaranteed though that all SoftReferences will get cleared before OutOfMemoryError is thrown, so they theoretically can't cause an OOME[*].

Typical use case example is keeping a parsed form of a contents from a file. You'd implement a system where you'd load a file, parse it, and keep a SoftReference to the root object of the parsed representation. Next time you need the file, you'll try to retrieve it through the SoftReference. If you can retrieve it, you spared yourself another load/parse, and if the GC cleared it in the meantime, you reload it. That way, you utilize free memory for performance optimization, but don't risk an OOME.

Now for the [*]. Keeping a SoftReference can't cause an OOME in itself. If on the other hand you mistakenly use SoftReference for a task a WeakReference is meant to be used (namely, you keep information associated with an Object somehow strongly referenced, and discard it when the Reference object gets cleared), you can run into OOME as your code that polls the ReferenceQueue and discards the associated objects might happen to not run in a timely fashion.

So, the decision depends on usage - if you're caching information that is expensive to construct, but nonetheless reconstructible from other data, use soft references - if you're keeping a reference to a canonical instance of some data, or you want to have a reference to an object without "owning" it (thus preventing it from being GC'd), use a weak reference.

Solution 3

In Java; order from strongest to weakest, there are: Strong, Soft, Weak and Phantom

A Strong reference is a normal reference that protects the referred object from collection by GC. i.e. Never garbage collects.

A Soft reference is eligible for collection by garbage collector, but probably won't be collected until its memory is needed. i.e. garbage collects before OutOfMemoryError.

A Weak reference is a reference that does not protect a referenced object from collection by GC. i.e. garbage collects when no Strong or Soft refs.

A Phantom reference is a reference to an object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed.

Source

Analogy: Assume a JVM is a kingdom, Object is a king of the kingdom, and GC is an attacker of the kingdom who tries to kill the king(object).

  • When King is Strong, GC can not kill him.
  • When King is Soft, GC attacks him but King rule the kingdom with protection until resource are available.
  • When King is Weak, GC attacks him but rule the kingdom without protection.
  • When king is Phantom, GC already killed him but king is available via his soul.

Solution 4

Weak Reference http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/ref/WeakReference.html

Principle: weak reference is related to garbage collection. Normally, object having one or more reference will not be eligible for garbage collection.
The above principle is not applicable when it is weak reference. If an object has only weak reference with other objects, then its ready for garbage collection.

Let's look at the below example: We have an Map with Objects where Key is reference a object.

import java.util.HashMap;   
public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> aMap = new 
                       HashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        System.out.println("Size of Map" + aMap.size());

    }
}

Now, during the execution of the program we have made emp = null. The Map holding the key makes no sense here as it is null. In the above situation, the object is not garbage collected.

WeakHashMap

WeakHashMap is one where the entries (key-to-value mappings) will be removed when it is no longer possible to retrieve them from the Map.

Let me show the above example same with WeakHashMap

import java.util.WeakHashMap;

public class Test {

    public static void main(String args[]) {
        WeakHashMap<Employee, EmployeeVal> aMap = 
                    new WeakHashMap<Employee, EmployeeVal>();

        Employee emp = new Employee("Vinoth");
        EmployeeVal val = new EmployeeVal("Programmer");

        aMap.put(emp, val);

        emp = null;

        System.gc();
        int count = 0;
        while (0 != aMap.size()) {
            ++count;
            System.gc();
        }
        System.out.println("Took " + count
                + " calls to System.gc() to result in weakHashMap size of : "
                + aMap.size());
    }
}

Output: Took 20 calls to System.gc() to result in aMap size of : 0.

WeakHashMap has only weak references to the keys, not strong references like other Map classes. There are situations which you have to take care when the value or key is strongly referenced though you have used WeakHashMap. This can avoided by wrapping the object in a WeakReference.

import java.lang.ref.WeakReference;
import java.util.HashMap;

public class Test {

    public static void main(String args[]) {
        HashMap<Employee, EmployeeVal> map = 
                      new HashMap<Employee, EmployeeVal>();
        WeakReference<HashMap<Employee, EmployeeVal>> aMap = 
                       new WeakReference<HashMap<Employee, EmployeeVal>>(
                map);

        map = null;

        while (null != aMap.get()) {
            aMap.get().put(new Employee("Vinoth"),
                    new EmployeeVal("Programmer"));
            System.out.println("Size of aMap " + aMap.get().size());
            System.gc();
        }
        System.out.println("Its garbage collected");
    }
}

Soft References.

Soft Reference is slightly stronger that weak reference. Soft reference allows for garbage collection, but begs the garbage collector to clear it only if there is no other option.

The garbage collector does not aggressively collect softly reachable objects the way it does with weakly reachable ones -- instead it only collects softly reachable objects if it really "needs" the memory. Soft references are a way of saying to the garbage collector, "As long as memory isn't too tight, I'd like to keep this object around. But if memory gets really tight, go ahead and collect it and I'll deal with that." The garbage collector is required to clear all soft references before it can throw OutOfMemoryError.

Solution 5

The only real difference between a soft reference and a weak reference is that

the garbage collector uses algorithms to decide whether or not to reclaim a softly reachable object, but always reclaims a weakly reachable object.

Share:
231,756
driekken
Author by

driekken

Updated on July 08, 2022

Comments

  • driekken
    driekken almost 2 years

    What's the difference between java.lang.ref.WeakReference and java.lang.ref.SoftReference ?

    • Ajeet Ganga
      Ajeet Ganga almost 9 years
      SoftReferences are type of (not really but for discussion sake) WeakReferences which are usually collected when JVM thinks it is out of memory.
    • Pacerier
      Pacerier over 6 years
      @AjeetGanga, Loose weak refs are always collected whenever the GC runs. See stackoverflow.com/a/46291143/632951
  • Jack BeNimble
    Jack BeNimble over 12 years
    Particularly useful for the explanation of when weak objects would be used.
  • Yaroslav Mytkalyk
    Yaroslav Mytkalyk over 11 years
    But in Android it isn't advised for caches developer.android.com/reference/java/lang/ref/…
  • fabspro
    fabspro about 11 years
    @DoctororDrive tbf the question was about java, not dalvik! :-P
  • xehpuk
    xehpuk about 9 years
    You may get a NullPointerException in aMap.get().put(...).
  • supercat
    supercat about 9 years
    A key point about the proper use of a WeakReference is that in places where one should be using it, the fact that one may remain valid for a little while after the reference goes out of scope may be tolerable, but is not desirable.
  • Bitcoin Cash - ADA enthusiast
    Bitcoin Cash - ADA enthusiast about 9 years
    Your first HashMap example looks wrong. When you do "aMap.put(emp, val);" both 'emp' and 'val' are strong references. Internally, a new variable is created to hold 'emp' and 'val' so when you do "emp = null;" you are just nullifying the "emp" variable, but not the variable internally to the hash map (which is still holding the original Employee object). Therefore the hash map will still hold a strong reference to 'emp' regardless of what you do with the 'emp' variable outside.
  • ToolmakerSteve
    ToolmakerSteve over 8 years
    @Tiago. No. Presumably by "first example" you are referring to the WeakHashMap example (since that is the first one that is demonstrating Weak behavior). Look at doc for "WeakHashMap": "An entry in a WeakHashMap will automatically be removed when its key is no longer in ordinary use. " The entire point of using WeakHashMap is that you don't have to declare/pass-in a WeakReference; the WeakHashMap does that for you, internally. docs.oracle.com/javase/7/docs/api/java/util/WeakHashMap.html
  • ToolmakerSteve
    ToolmakerSteve over 8 years
    Soft reference ... until memory is available doesn't make sense. Do you mean is eligible for collection by garbage collector, but probably won't be collected until its memory is needed for another use?
  • ToolmakerSteve
    ToolmakerSteve over 8 years
    Not a good description of phantom references. Also, you've listed the 4 types in a peculiar order. "phantom" is the weakest type, not the strongest type. The traditional order to list these is "strong, soft, weak, phantom". And I have no idea where you got the notion that phantom objects are used for caching mechanisms. AFAIK, they are a temporary state seen only by the GC, not something that an ordinary programmer would work with.
  • Premraj
    Premraj over 8 years
    yes, garbage collector won't collect the reference until the memory is available.
  • Adelin
    Adelin about 8 years
    I like simple explained stuff, without too much bla bla bla +1 from me !
  • Adelin
    Adelin about 8 years
    Took 0 calls to System.gc() to result in weakHashMap size of : 0 is the output of your second program ?
  • Admin
    Admin over 7 years
    I'm struggling to understand what is the use of WeakHashMap if it always produces weak reference to its key value object?
  • Ravindra babu
    Ravindra babu over 7 years
    Excellent summary with innovative example
  • riccardo.tasso
    riccardo.tasso almost 7 years
    Post no more available, you can find it on wayback machine: web.archive.org/web/20061130103858/http://weblogs.java.net/b‌​log/…
  • V.Vidyasagar
    V.Vidyasagar almost 7 years
    @ToolmakerSteve and all - Apologies for couple of things 1. the wrong explanation of Phantom references in the previous version of my answer, and 2. Delay in correcting the errors. Now the answer has been improved by correcting the errors
  • roottraveller
    roottraveller almost 7 years
  • Pacerier
    Pacerier over 6 years
    This is common sense... same goes for softref and phantomref.
  • Pacerier
    Pacerier over 6 years
    @YaroslavMytkalyk, Frankly, if Android wants to rewrite the behavior of a class, it should use its own namespace, not java.lang. Such abuse of synonyms is doing no one any good.
  • Pacerier
    Pacerier over 6 years
    @ATorras, Samir. I expanded on this answer here: stackoverflow.com/a/46291143/632951
  • Pacerier
    Pacerier over 6 years
    @supercat, There is only one proper use of WeakReference which is to observe GC runs. See elaboration: stackoverflow.com/a/46291143/632951
  • supercat
    supercat over 6 years
    @Pacerier: The author of that post is simply wrong. He neglects some other usage scenarios like event subscription, his second point is nonsensical, and his third point assumes that a programmer can do things that may not be possible. His first point is reasonable, but ties in directly with what I said. If code will frequently have to build and compare large immutable objects, for example, the building part will often be cheaper if code creates new objects without regard for whether they already exist, but a comparison between an object and itself (identical references) will be...
  • supercat
    supercat over 6 years
    ...much cheaper than a comparison between two different immutable objects that hold the same data. If code needs an object that matches an existing object, using a reference to the existing object (instead of a new one) will be helpful if those objects will end up being compared. If the object exists in the interned cache and nowhere else, however, returning a reference to that would be more expensive than, and offer no advantages over, creating a new object and returning a reference to that.
  • HighCommander4
    HighCommander4 over 6 years
    What about a cache where the key type's equals() is just object identity? Soft references seem like a waste there, because once a key object is no longer strongly reachable, no one will ever look up that mapping again.
  • user1506104
    user1506104 almost 6 years
    this time, the archive is no longer available
  • Basil Bourque
    Basil Bourque over 5 years
    For another example of WeakHashMap in action, with example app showing how entries are removed only after garbage-collection executes, see my Answer to the Question, Is WeakHashMap ever-growing, or does it clear out the garbage keys?.
  • Maverick Meerkat
    Maverick Meerkat over 5 years
    I disagree. Use WeakReference when you don't want to influence GC in anyway (You might want to save an object reference and then check later if it still exists, without any preference that it does). Use SoftReference if you want to influence the GC to try and keep the object (i.e. when you would prefer that the GC would keep it).
  • Maverick Meerkat
    Maverick Meerkat over 5 years
    A good example where to use WeakReference is in Android's AsyncTask - to keep an instance of the context. That way if the context dies (if activity - screen rotation, etc.), the AsyncTask won't have any strong reference to it, and so it can be garbage collected. Check youtu.be/…
  • Jose Quijada
    Jose Quijada almost 3 years
    Great explanation. This question can come up in Java related job interviews.
  • Alan
    Alan about 2 years
    I like the analogy.