Garbage Collection in Java – Requesting JVM to Run Garbage Collector

Free Java courses with 37 real-time projects - Learn Java

Garbage collection is one of the prime and most distinguishing features in Java. Before we dive into it, let us take a real-life example to understand how and why garbage collection is essential for programmers.

Okay, you are having the time of your life at a party hosted by your friend. There are cartons and packets lying all around the room while you dance to your merriment.

At that point, your friend says that his parents are in town and you immediately need to leave.

No questions asked, everyone scrambled for their belongings and left the party. Since you are your friend’s best mate, you decide to help him clean up all the mess.

However, you notice something strange, every time you take the trash out, you keep it beside the pavement and return to the comfort of your home.

A garbage truck comes by every day and picks up the trash bag from the pavement. This cycle continues. Every day you keep the trash along the pavement and the garbage collector comes and picks it up.

Imagine what would have happened if the garbage collection truck suddenly stopped coming!

Yes, for a few days, you would not even bother and put the trash back there itself. But after a few days, things would start to get ugly.

Garbage would be piling up and thus would cause foul smell throughout the neighborhood. This is the essence of garbage collection.

Garbage Collection in Java

The garbage collector in Java is solely responsible for deleting nullified references of objects.

In other languages, such as C or C++, the programmer is solely responsible for creating and deleting objects. This may result in memory depletion if the programmer forgets to dereference the objects.

In Java, programmers do not have to work on this. The JVM automatically destroys objects which have lost their reference.

Now, what do we mean when we say “lost their reference”?

Let us find out through a simple example.

Let us say we have a class called human which has a constructor Human(String name). This constructor initializes the current value of the string to the class variable name.

Now if we create an object of the class Human as follows.

Human object = new Human(“Shraman”);

The JVM creates a reference of the name “object” and points it to the data Shraman.

Now if I write
object=null;

The pointer to the value “Shraman” is now nullified. I cannot access the value anymore as there was only one reference pointing to it. This is unreachability of objects in memory.

This object of human named “Shraman” is now eligible for garbage collection.

An object is eligible for garbage collection if there are no references to it in the heap memory.

There are a few ways to make an object eligible for garbage collection. They are:

  1. You can nullify the reference variable.
  2. You can assign the same pointer to a different object.
  3. All objects created inside a method lose their reference outside the method and are thus eligible for garbage collection.
  4. Using Island of Isolation.

Finalization in Java

As soon as the garbage collector clears the object, the compiler executes the finalize() method.

This method generally contains actions which the JVM performs just before the object gets deleted.

The Object class contains the finalize() method. Remember to override the finalize method in the class whose objects will be garbage collected.

The finalize method throws a checked exception called “Throwable”.

What is the Island of Isolation?

Island of isolation, the name sounds cool and sad at the same time, right?

Let us dive into this topic first, and we will go through the remaining topics after that.

When there are a group of objects which are not referenced by any active object in the program, all the unreferenced objects are in the Island of Isolation.

Even if a single object has lost all of its references, it is still in the Island of Isolation.

Do note that objects in the Island of Isolation reference each other.

Java program to illustrate the use of the Garbage collector.

package com.dataflair.garbagecollection;
class Human
{
    @Override
    protected void finalize() throws Throwable
    {
        System.out.println("Garbage collector in action! Deleted one object!");
    }
    String name;
    Human(String name)
    {
        this.name=name;
    }
}
public class IslandOfIsolation 
{
   
    public static void main(String[] args) {
        Human human1 = new Human("Shraman");
        Human human2 = new Human("Debanjan");
        human1.name=human2.name;
        human2.name=human1.name;

        human1=null;//Nullifying the first object

        human2=null;//nullifying the second object. 


        System.gc();//calling the garbage collector. 

    }
}

Output:

Garbage collector in action! Deleted one object!
Garbage collector in action! Deleted one object!

When a garbage collector destroys an object, the JVM calls the finalize() object at most one time. This is because the finalize method object prints the statement two times. One for each object.

One very important thing to note is that the function finalize is overridden in the Human class, i.e, the class whose object we are destroying.

Do understand that you need to override the finalize method in the class whose object you are destroying.

For example, in the above code, if you override the finalize method in the IslandOfIsolation class, you would not see the print statements.

This is because the garbage collector collects the object of the type human and then runs the finalize method on the Human objects.

Methods for calling the Garbage Collector in Java

ways to call the garbage collector in java

There are 2 ways to call the garbage collector in java.

  • You can use the Runtime.getRuntime().gc() method- This class allows the program to interface with the Java Virtual machine. The “gc()” method allows us to call the garbage collector method.
  • You can also use the System.gc() method which is common.

The application is simple. There are no syntaxes for these individual methods in Java.

However, you cannot guarantee that these statements would run the garbage collector. This is because the Java Virtual Machine performs cleanup.

Important points on Usage of Garbage Collector

  1. The garbage collector calls the finalize method, not the JVM.
  2. The finalize method in the Object class does not have any implementation of its own. hence you can override it to suit your programming needs. Marvellous, right?
  3. All the uncaught exceptions in the finalize method get ignored.
  4. The finalize method does not execute more than once for a single object.

How Garbage Collection Works

In the program above you saw how the garbage collection gets implemented in a program. But some of you would want to know the nitty-gritty details about it.

Well, don’t worry we have got you covered. In this section we would be diving into the depths of garbage collection in Java and why it is such a magical and unique concept.

The objects are in the heap memory of Java. Most of you would already be familiar with that.

However, there are many subdivisions in this heap memory that help the Garbage Collector to target which object to clean next.

There are plenty of Java Virtual machines out there, but here we will be talking about the Oracle HotSpot JVM.

The HotSpot uses a strategy called “Generational Garbage Collection Strategy” during Garbage collection.

This may sound confusing and intricate at first but it is not. This strategy simply works just like an LRU Cache.

The memory(heap) consists of the following parts

  1. Young Generation – This part of memory, as the name suggests, houses the objects which are new to the system. This memory again consists of two parts, the Eden and the Survivor places. If the object does not lose its references immediately, it moves to the survivor parts of the memory. The garbage collector collects objects from the Young Generation. This is a minor garbage collection event.
  2. Old Generation – This part of the memory houses the objects which have been connected with their references for a considerable amount of time. When a garbage collection removes objects from this part of the memory. This is a Major Garbage collection.
  3. Permanent Generation – This memory segment contains metadata about the classes and methods in the program. Since these are long-lasting they are moved to the permanent section. However, these objects are also cleaned up if a particular class does not exist anymore. The string pool in Java is in the permanent generation.

Types of Garbage Collectors in HotSpot Java

There are a few different types of garbage collectors in HotSpot java:

types of garbage collectors in HotSpot java

  1. Serial – This collector primarily relies on a single thread and continues to serially collect unreferenced objects.
  2. Parallel – This collector uses multiple threads for collecting unreferenced objects in Java. There are two variants to it. The collector can use multiple threads for Minor garbage collection and one thread for Major garbage collection or vice versa.
  3. CMS – This collector stands for Concurrent Mark Sweep. This essentially means that this collector uses multiple threads for major and Minor garbage collection, however, there is one important advantage of this collector. This collector does not allow the garbage collection to stop the application itself. This means that the collector is concurrent with the application, i.e, runs alongside the application itself. However if the collector needs to update some objects from the young to the old generation but the collector itself is busy, a race condition occurs. This collection also uses up a lot of processing power.
  4. Garbage First(G1) – This is similar to the CMS in terms of concurrency and usage of multithreading. This divides the memory into several parts based on the size. The collector specifically clears the part of the memory which has the most number of unreferenced objects at first. Justifies the name, doesn’t it?

Garbage Collection Roots

Each and every object tree has roots. As long as the JVM can reach these roots, the entire tree is traversable.

But wait a second, what are these roots?

This is simply an object which is accessible outside the heap memory.

The non-reachable object trees are removed by the garbage collector itself.

There are 4 types of GC roots in Java:

  1. Local variables – These are GC roots because these are kept alive by a thread process. Local variables are never seen as an object reference.
  2. Java Threads – These are the live threads in Java. The JVM considers them as GC roots simply because these are live objects.
  3. If you take into account the case of static variables you will notice an interesting behavior. Although they are variables that might make you think that they would be treated like local variables, they are not. Static variables relate to classes. Now classes themselves are susceptible to garbage collection. If a class gets removed, the garbage collector collects all the details of the class along with the static variables with it.
  4. JNI references – These references are the ones that the native code makes to the objects which are garbage collected. This happens when the native code still requires reference to the object but there are no live references to the object in the code itself.

Best Practices of Garbage Collection in Java

In entry-level programming, a programmer does not need to consider the collection of unreferenced objects in Java. However, while developing applications, collectors along with their flags are very essential.

Unlike C and C ++, Java allows automatic garbage collection by default. “With great power comes great responsibility”. So to particularly leverage the power of collection we need to understand it.

Collector choice is a primary concern as the wrong collector can hinder performance and render the application useless.

For backend purposes, the CMS collector can prove to be useful in spite of having the disadvantage of stopping the application itself during garbage collection.

However, the frontend of the application must not implement CMS because the UI must always be responsive. This calls for G1 collectors which can run concurrently with the application in itself.

Whenever you are using garbage collections in Java it is important to note that you can never predict when the garbage collector will run. You can try to explicitly call the garbage collector by System.gc() and Runtime.gc().

However, even after explicitly calling the Garbage collector there is no guarantee that it will actually work.

Benefits of garbage collection in Java

The benefits of garbage collection in Java are as follows:

  • In languages such as C and C++, the programmer has to explicitly destroy objects and free up memory. However, in Java, the programmer can focus on the logic and the GC takes care of the rest.
  • Even if the garbage collection is affecting the performance of the application negatively, one can always fine-tune the GC by manipulating flags( just like we discussed) to effectively use the collector.

Summary

In this article, we came to know about Garbage Collection in Java, why it is useful, and how we can leverage it to our advantage.

This is a very important thing to know about Java and is a very frequently asked question in interviews.

Did you like our efforts? If Yes, please give DataFlair 5 Stars on Google

follow dataflair on YouTube

Leave a Reply

Your email address will not be published. Required fields are marked *