Weak References in Java/Kotlin Explained (With illustrations)

Weak References in Java/Kotlin Explained (With illustrations)

I’ve heard about weak references for the first time when I was reading more in LeakCanary library’s documentation to see how it works. But I didn’t quite get it when I googled it; Also, all of the examples I read weren’t practical which made it harder to grasp the concept.

There are 4 types of references in Java: Strong, Soft, Weak, and Phatom.

We will focus on Strong and Weak references in this article.

Strong Reference

It is the reference that gets created by default whenever we create any object. This reference will prevent the garbage collector (GC) from destroying this object.

So for example, when we create an instance of a class called Dummy; Like in the following image:

StrongReference.png

A new object of type Dummy gets created in memory and myObject has a strong reference to it.

When we try to print myObject before garbage collector runs; It will print the address of the object in memory.

StrongReference – Before GC.png

But, what happens when garbage collector runs? (We simulate this by forcing GC to run by writing System.gc())

StrongReference – After GC.png

The object will stay in the memory and nothing will happen as this is what we expected (Strong references prevents GC from destroying the referenced object).

Weak Reference

Here is its definition from Wikipedia:

A weak reference is a reference that does not protect the referenced object from collection by a garbage collector, unlike a strong reference.

Which means that when we create a weak reference to an object, and garbage collector runs, it will clear the object from memory right away (If there are no other strong references to this object).

Lets take this example and then I will explain when we may need such thing.

WeakReference.png

In the previous image, we created an object of type Dummy and myObject has a weak reference to it.

So before garbage collector runs, There is now an object of type Dummy in memory which is referenced by myObject using a weak reference.

We will now print that Dummy object to make sure that it exists in memory; using .get() method on myObject variable.

Note: The get() method returns the referent that the WeakReference refers to or returns null if the referenced object is cleared.

WeakReference – Before GC.png

So the memory address of the Dummy object we created is printed in the console which confirms that the object is in memory now.

But, what happens if we run the garbage collector now?

WeakReference – After GC.png

Here, you can see that null is printed and the Dummy instance is removed from memory; which makes sense as the description of the weak references says that if there is a weak reference to an object and garbage collector runs, it will remove this object from memory.

Example using both Strong & Weak references

For this example, we have a variable myObject which holds a strong reference to an Dummy instance.

S & W.png

So lets see what happens before and after garbage collector runs.

S & W – Before GC.png

S & W – After GC.png

Here, The Dummy() object in memory doesn't get destroyed after GC runs as there is a strong reference (myObject) that references it.

And for the weak reference, it doesn't get cleared by GC as the object (Dummy()) has another strong reference (myObject) that is attached to it.

Which is the real benefit of weak references, they only keep a reference to an object as long as it exists in memory and gets cleared when all the strong references related to this object gets cleared.

Real World Example in Android

We all know that it is a bad idea to keep a reference to a context in singletons. If you try to do so, Android Studio will give you a warning stating that:

Do not place Android context classes in static fields (static reference to MySingleton which has field context pointing to Context); this is a memory leak

Android.png

And this can cause memory leaks.

So, how to solve this?

Using weak references!

Here is how to use it:

Android 2.png

Now, the warning disappears as it doesn't cause a leak, because when the MainActivity instance gets destroyed (onDestroy gets called), this weak reference to its context will get destroyed too; so no memory leaks occur.

Conclusion

WeakReference is a very important concept to have in your toolbox when developing Android apps, libraries, or any Java/Kotlin projects; However, you have to make sure you use it correctly in order to avoid making any unexpected behavior in your code.