Understanding the Java Garbage Collection Concept is one of the most important steps towards developing any reliable Java application, with good performance.

A typical modern Java Virtual Machine (JVM) uses several different types of garbage collectors.

“Garbage Collection” as the name suggests, is used to remove the objects that are no longer needed by the Java application. The Java Garbage Collector will identify those objects and remove those from the memory thereby freeing the memory for the new objects.

JVM Garbage Collection Types

There are four different types of Garbage Collectors available ...

  • Serial Collector
  • Parallel Collector
  • Parallel Compacting Collector
  • Concurrent Mark-Sweep (CMS) Collector

 

One type that's often used for objects that have been around for a while is called Mark-and-Sweep. It basically involves starting from known "live" objects (the so-called garbage collection roots), following all chains of object references, and marking every reachable object as "live".

Once this is done, the sweep stage can reclaim those objects that haven't been marked as "live".

For this process to work, the JVM has to know the location in memory of every object reference. This is a necessary condition for a garbage collector to be precise (which Java's is).

With the “mark and sweep” algorithm, when we run the main() thread, (one thread that will always be there along with other threads), this thread can either be alive or the execution is complete, but it may also be the case that while main() thread is silent, some other threads are working on it. The entire life cycle of the thread is maintained on its stack trace. When the garbage collector finds this that the particular object is no longer more accessible to any threads, i.e. it is unreachable or no references exist to the object, such an object becomes vulnerable to be caught by the garbage collector.

Now, to make the object unreachable, it is clear that the references to that object should cease to exist and this can be done by removing the reference to the object either by making the references null or by reassigning a new object to the existing reference for the current object.

What if the “Reference is Null”?

Now, all we are doing here is to nullify the references to an object and once there are no reachable references, the object looses its importance and is no longer needed thus becomes eligible for Garbage Collection.

An example ...

public class RefrenceGarbage{
public static void main(String [] args) {
StringBuffer greeting = new StringBuffer("Hello");
System.out.println(greeting);
greeting = null;
}
}

In the example code above, we can see that before the reference to the StringBuffer object “Hello” is removed or nulled by setting 'greeting' to null, there can be seen on the console the output of println(), which is “Hello”, but it more refers to “Hello” after 'greeting' = null;

Try “Reassigning a Reference Variable”

Another way, in effect, to remove the reference to a particular object and making it eligible for Garbage Collection is to set the reference variable which currently refers to it to a new object. Thus, re-assigning the reference variable. Let’s have a look at the following code –

class RefrenceGarbage{
public static void main(String [] args) {
StringBuffer greeting = new StringBuffer("Hello");
StringBuffer greeting2 = new StringBuffer("Howdy");
System.out.println(greeting);
greeting = greeting2;
}
}

How about “Isolating a Reference”…

This time, we are not removing the references, but just isolating them. Consider a case where a reference to an object is also used to refer to another reference to the same object. Now imagine that two such instances exist and that they refer to each other. If all other references to these two objects are removed, then even though each object still has a valid reference, there will be no way for any live thread to access either object. When the garbage collector runs, it will remove such objects.

However, we must keep in mind that the garbage collection is not completely within our control and the way the JVM works and selects the algorithm is all left to JVM’s discretion.