1. Overview

In this article, we’ll have a look at the concept of a weak reference – in the Java language.

We’re going to explain what these are, what they’re used for, and how to work with them properly.

2. Weak References

A weakly referenced object is cleared by the Garbage Collector when it’s weakly reachable.

Weak reachability means that an object has neither strong nor soft references pointing to it. The object can be reached only by traversing a weak reference.

First off, the Garbage Collector clears a weak reference, so the referent is no longer accessible. Then the reference is placed in a reference queue (if any associated exists) where we can obtain it from.

At the same time, formerly weakly-reachable objects are going to be finalized.

2.1. Weak vs Soft References

Sometimes the difference between weak and soft references is unclear. Soft references are basically a big LRU cache. That is, we use soft references when the referent has a good chance of being reused in the near future.

Since a soft reference acts as a cache, it may continue to be reachable even if the referent itself is not. As a matter of fact, a soft reference is eligible for collection if and only if:

  • The referent is not strongly reachable
  • The soft reference is not being accessed recently

So a soft reference may be available for minutes or even hours after the referent becomes unreachable. On the other hand, a weak reference will be available only for as long as its referent is still around.

3. Use Cases

As stated by Java documentation, weak references are most often used to implement canonicalizing mappings. A mapping is called canonicalized if it holds only one instance of a particular value. Rather than creating a new object, it looks up the existing one in the mapping and uses it.

Of course, the most known use of these references is the WeakHashMap class. It’s the implementation of the Map interface where every key is stored as a weak reference to the given key. When the Garbage Collector removes a key, the entity associated with this key is deleted as well.

For more information, check out our guide to WeakHashMap.

Another area where they can be used is the Lapsed Listener problem.

A publisher (or a subject) holds strong references to all subscribers (or listeners) to notify them about events that happened. The problem arises when a listener can’t successfully unsubscribe from a publisher.

Therefore, a listener can’t be garbage collected since a strong reference to it’s still available to a publisher. Consequently, memory leaks may happen.

The solution to the problem can be a subject holding a weak reference to an observer allowing the former to be garbage collected without the need to be unsubscribed (note that this isn’t a complete solution, and it introduces some other issues which aren’t covered here).

4. Working With Weak References

Weak references are represented by the java.lang.ref.WeakReference class. We can initialize it by passing a referent as a parameter. Optionally, we can provide a java.lang.ref.ReferenceQueue:

Object referent = new Object();
ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();

WeakReference weakReference1 = new WeakReference<>(referent);
WeakReference weakReference2 = new WeakReference<>(referent, referenceQueue);

The referent of a reference can be fetched by the get method, and removed manually using the clear method:

Object referent2 = weakReference1.get();
weakReference1.clear();

The pattern for safe working with this kind of references is the same as with soft references:

Object referent3 = weakReference2.get();
if (referent3 != null) {
    // GC hasn't removed the instance yet
} else {
    // GC has cleared the instance
}

5. Conclusion

In this quick tutorial, we had a look at the low-level concept of a weak reference in Java – and focused on the most common scenarios to use these.