Skip to main content

Types of References in Java(Strong, Soft, Weak, Phantom)

As being a Java programmer we all know what is a reference, But let’s go through this again which it will help us to understand our current topic which is “Types of References in Java”.

All types in Java lies under two categories
  1. Primitive Types: There are 8 primitive types (byte, short, int, long, float, double, char and boolean) in Java which holds their values directly in form of bits. 
  2. Reference Types: All types other than primitive lies under the category of reference types e.g. Classes, Interfaces, Enums, Arrays etc. 
We can define a reference similar as primitive as

Employee emp = new Employee();

Here “new Employee()” is actually the object which gets space in heap, and “emp” is called reference variable which is holding the object, holding means “emp” variable stores the address of the object in form of bits.

As long as “emp” is holding this object it is not eligible for garbage collection. Because it is still in use and is reachable from “emp” reference.

Now if we assign a new object to “emp” it will hold the address of the new object and because now nobody is holding the reference of that old employee object it will become eligible for garbage collection.

Based on the behavior of references with Garbage Collector we can divide references into 4 sections given below in order from strongest to weakest.
  1. Strong References
  2. Soft References
  3. Weak References
  4. Phantom References

Strong References

These are your regular object references which we code daily:

Employee emp = new Employee();

The variable “emp” holds a strong reference to an Employee object and objects that are reachable through any chain of strong references are not eligible for garbage collection.
Usually, this is what you want but not always. Now suppose we are fetching lots of employees from database in a collection or map, and we need to do a lot of processing on them regularly, So in order keep performance we will keep them in the cache.

As far as this is good but now we need different data and we don’t need those Employee objects and these are not referenced from anywhere except the cache. Which is causing a memory leak because these objects are not in use but still not eligible for the garbage collection and we cannot remove those objects from cache because we don’t have reference to them?
So here either we need to empty the entire cache manually which is tedious or we could use other kind references e.g. Weak References.

Weak References

A weak reference does not pin an object into memory and will be GC’d in next GC cycle if not referenced from other references. We can use WeakReference class which is provided by Java to create above kind of caches, which will not store objects which are not referenced from somewhere else.

WeakReference<Cache> cache = new WeakReference<Cache>(data);

To access data you need to call cache.get(). This call to get may return null if the weak reference was garbage collected: you must check the returned value to avoid NPEs.
Java provides collections that use weak references e.g., the WeakHashMap class stores keys (not values) as weak references. If the key is GC’d then the value will automatically be removed from the map too.

Since weak references are objects too we need a way to clean them up (they’re no longer useful when the object they were referencing has been GC’d). If you pass a ReferenceQueue into the constructor for a weak reference then the garbage collector will append that weak reference to the ReferenceQueue before they’re finalized or GC’d. You can periodically process this queue and deal with dead references.

Soft References

A SoftReference is like a WeakReference but it is less likely to be garbage collected. Soft references are cleared at the discretion of the garbage collector in response to memory demand. The virtual machine guarantees that all soft references to softly reachable objects will have been cleared before it would ever throw an OutOfMemoryError.

Phantom References

Phantom references are the weakest of all reference types, calling get on them will always return null. An object is phantomly referenced after it has been finalized, but before its allocated memory has been reclaimed, As opposed to weak references which are enqueued before they’re finalized or GC’d Phantom references are rarely used.

So how are they useful? When you construct a phantom reference you must always pass in a ReferenceQueue. This indicates that you can use a phantom reference to see when your object is GC’d.

Hey, so if weak references are enqueued when they’re considered finalize but not yet GC’d we could create a new strong reference to the object in the finalizer block and prevent the object being GC’d. Yep, you can but you probably shouldn’t do this. To check for this case the GC cycle will happen at least twice for each object unless that object is reachable only by a phantom reference. This is why you can run out of heap even when your memory contains plenty of garbage. Phantom references can prevent this.

Comments

Post a Comment

Popular posts from this blog

What is Variable Shadowing and Hiding in Java

Java allows us to declare a variable whenever we need it, We can categorize all our variables into 3 categories which have different-different scopes Instance Variables - Defined inside a class and have object level scope. Class Variables - Defined inside a class with static keyword, have class level scope common to all objects of the same class Local Variables - Defined inside a method or in any conditional block, have the block-level scope and only accessible in the block where it defined. What is Variable Shadowing Variable shadowing happens when we define a variable in a closure scope with a variable name and we have already defined a variable in outer scope with the same name. In other words, when a local variable has the same name as one of the instance variable, the local variable shadows the instance variable inside the method block. In the following example, there is an instance variable named x and inside method printLocalVariable(), we are shadowing it by the local ...

Why String is Immutable and Final in Java

While coding in any programming language we always require some predefined types which we can use to write the code and every programming language provides these types in its way e.g. Java provides primitive types ( int, long, char float etc) and reference types (custom types like Object, String, Thread ). For string manipulation, Java provides a class java.lang.String which gives us a way to create string objects and provides different behaviors to operate on those objects e.g. replace(), length() String name = "Naresh"; System.out.print(name.length()); System.out.print(name.isEmpty()); Whenever we talk about String class in Java we say it is i mmutable in nature and all string literals are stored in String Constant Pool (SCP) . Prior to Java 7 String Constant Pool belongs to Permanent Generation area of heap which means Garbage Collector will not touch it in normal scenarios. But from Java 7 onwards string constant pool is not part of Perm Gen but live with o...

Creating objects through Reflection in Java with Example

In Java, we generally create objects using the new keyword or we use some DI framework e.g. Spring to create an object which internally use Java Reflection API to do so. In this Article, we are going to study the reflective ways to create objects. There are two methods present in Reflection API which we can use to create objects Class.newInstance() → Inside java.lang package Constructor.newInstance() → Inside java.lang.reflect package However there are total 5 ways create objects in Java, if you are not aware of them please go through this article 5 Different ways to create objects in Java with Example . Both Class.newInstance() and java.lang.reflect.Constructor.newInstance() are known as reflective methods because these two uses reflection API to create the object. Both are not static and we can call earlier one on a class level object while latter one needs constructor level object which we can get by using the class level object. Class.newInstance() The Class class is th...