Let’s take a look at the concepts of the garbage collector in Java and various reference object types that it can handle!
As we all know that Garbage Collector reclaims memory from objects which are eligible for garbage collection, but do we know that the eligibility criteria is based upon the kind of references pointing to that object.
There are FOUR types of object references in Java.
In every Java program, objects are the way to hold and manipulate data:
StringBuilder sbObject = new StringBuilder();
The new keyword in the above code snippet creates a StringBuilder object and stores it in a variable sbObject as a strong reference. This behavior is the default level of strength for all the new objects that we create.
Any object with at least one strong reference is not eligible for garbage collection. It only becomes eligible for collection when we nullify its reference.
sbObject = null
A soft reference can be created to an object by wrapping its instance in a java.lang.ref.SoftReference object:
StringBuilder sbObject = new StringBuilder (); SoftReference<StringBuilder> sbSoftRef = new SoftReference<>(sbObject); sbObject = null;
The first line of the above mentioned code snippet is similar to the Strong Reference creation of the Object. The second line of the code is used to create the SoftReference of the object created earlier. Based on these two lines of codes now there are two reference objects of the StringBuilder Class. However, the third line nullifies the strong reference, and now the object only boasts of a soft reference.
Objects with only soft references to it are collected if and only if the JVM absolutely needs memory to allocate to new objects and is on the brink of throwing an OutOfMemory error.
Soft references are intended for use in memory-sensitive caches, the JVM will compromise with “you” until it can’t anymore for the cache memory.
A weak reference can be created to an object by wrapping its instance in a java.lang.ref.WeakReference object:
StringBuilder sbObject = new StringBuilder(); WeakReference<StringBuilder> sbWeakRef = new WeakReference<>(sbObject); sbObject = null
In the above mentioned code snippet, once we nullify the strong reference in the third line, the object immediately becomes eligible for GC.
Garbage collector can collect an object if only weak references are pointing towards it and they are eagerly collected.
Weak references are intended for use in storing Meta Data, e.g., ClassLoader reference. If no class is loaded then there is no point in keeping reference of ClassLoader, thus a WeakReference objects makes ClassLoader eligible for GC as soon as the last strong reference is removed.
A phantom reference can be created to an object by wrapping its instance in a java.lang.ref.PhantomReference object:
StringBuilder sbObject = new StringBuilder(); ReferenceQueue<StringBuilder> refQueue = new ReferenceQueue<>(); PhantomReference<StringBuilder> sbPhantomRef = new PhantomReference<>(sbObject, refQueue); sbObject = null
After nullifying the strong reference in the fourth line of the above mentioned code snippet, the object immediately becomes eligible for GC. We have discussed about the ReferenceQueue in detail in a separate post. For now, just remember that PhantomReference, unlike soft and weak references, is useless without a ReferenceQueue.
A phantom reference is enqueued as soon as the object it is referring to has been finalized by the garbage collector. Finalized here means that the finalize() method has been invoked. The finalize() method is invoked by the GC just before collecting the object and this is for the benefit of the application that created them.
PhantomReference objects are created to “provide a more flexible alternative to finalize()”.