Do you know that Java not only have one reference type but actually four of them?

Many developers are not aware of these types and what’s the advantage of having them. I’m not sure why this concept is not evident among us, since, these types are available since Java 1.2 release.

Let’s deep dive into reference types to understand their usage.

Why do we need so many different types?

Consider I’ve a table (such as user details) that contains data which is frequently accessed. I understand a bit about performance, so instead of dipping into database every time to fetch data from this table. I’m going to take the route of Cache. To simplify things, let’s go ahead with an in-memory cache like a Map.

Whenever application needs data for a particular user, it will check if data is available in Cache, otherwise it will retrieve the data from database, update the Cache with this new data and will return data from the Cache.

Now the question arises ‘Is it improving the performance?’ Short answer is It Depends. If the table has few records only, it will work like charm. But, if the table holds large number of entries, it will cause Cache to increase linearly with the request. As, I stated earlier I know a bit about performance. I will cap the size of Cache, so that when max size is reached, oldest entries from Cache are evicted.

Well, Cache size cap solves the problem partially only. What if, there are some entries in Cache, which are rarely used later on. These entries will eat up memory unnecessarily. So, the big question is ‘How should we delete these entries sitting in Cache which are not being used later on?’.

As you have guessed, the answer is Reference Types.

I can’t wait to know more about the Reference Types

java.lang.ref package contains the below four reference types:

  1. Strong Reference
  2. Weak Reference
  3. Soft Reference
  4. Phantom Reference

Strong Reference

You can see Strong Reference everywhere in Java. We create an object and then assign it to a reference.
Strong Reference is never Garbage Collected.

1
StringBuilder sb = new StringBuilder();

In the above snippet, sb is the Strong Reference to StringBuilder class object.

Weak Reference

A Weak Reference, simply put, is a reference that isn’t strong enough to force an object to remain in memory. This type of reference is eligible for Garbage Collection.

1
2
3
4
5
StringBuilder sb = new StringBuilder();

WeakReference<StringBuilder> sbWeakRef = new WeakReference<>(sb);

sb = null;

In the above snippet, sbWeakRef is the Weak Reference to StringBuilder class object. After nullifying the strong reference in the third line, the object immediately becomes eligible for GC.

Well there are two different levels of weakness: Soft and Phantom.

Soft Reference

A Soft Reference is basically a weak Reference Object that remains in memory as long as possible. _GC_ reclaims this memory only when it sees that there is no more memory to allocate for new objects and it is on brink of throwing OutOfMemoryError.

1
2
3
4
5
StringBuilder sb = new StringBuilder();

SoftReference<StringBuilder> sbSoftRef = new SoftReference<>(sb);

sb = null;

In this phase, we can still retrieve a strong reference to the object by calling the get method of the SoftReference object, which returns null if the object is already collected:

1
sb = sbSoftRef.get();

Phantom Reference

A Phantom Reference Object is useful only to know exactly when an object has been effectively removed from memory: normally they are used to fix weird finalize() revival/resurrection behavior, since they actually do not return the object itself but only help in keeping track of their memory presence.

1
2
3
4
5
6
7
StringBuilder sb = new StringBuilder();

ReferenceQueue<StringBuilder> refQ = new ReferenceQueue<>();

PhantomReference<StringBuilder> sbPhantomRef = new PhantomReference<>(sb, refQ);

sb = null;

That’s it for now related to the Reference Types in Java. For Concurrency related problems, check my Github.