Understanding Garbage Collection in Java

What Is Garbage Collection In Java?

Garbage is an unreferenced object in Java. Garbage Collection is a process of automatically releasing unused memory at runtime. It is a method of destroying unused objects.

For this purpose, we used the free() and delete() functions in C and C++ respectively. Java, however, performs it automatically. As a result, Java provides better memory management.

A Java application obtains objects from memory as needed. As part of the Java virtual machine (JVM), garbage collection (GC) is responsible for automatically detecting and reusing memory no longer being used by Java applications. A Java application developer does not have to explicitly release memory objects which are not being used by the Java Virtual Machine, because memory reclaim is automatic.

The GC operation assumes most Java objects are short-lived and are reclaimed shortly after being created. Garbage collection keeps heap memory efficient by removing unreferenced objects.

How does Garbage Collection Work in Java?

There is an automatic garbage collection process in Java. A programmer does not have to mark objects for deletion explicitly.

The JVM implements garbage collection. Each JVM can implement garbage collection in its own way. However, it should be able to work with the objects present in the heap memory, identify unreachable objects, and destroy them through compaction according to the standard JVM specs. A program containing an unreferenced or unused object will no longer get recognized. It allows the memory used by unreferenced objects to get reclaimed.

Types of Garbage Collection

Two types of garbage collection activity usually happen in Java:

A minor or incremental Java garbage collection occurs when non-reachable objects get removed from the heap memory of the young generation.

A major or full Java garbage collection occurs when objects in the old or permanent heap memory that survived the minor garbage collection get removed. Garbage collection occurs less frequently in the old generation compared to the young.

Performance Impact of Java Garbage Collection

To determine which memory to free, garbage collection consumes CPU resources in the JVM. A program that gets stopped or consumes high CPU resources will negatively affect the end-user experience, and they will complain that the application is slow.

As Java garbage collectors have evolved over time, they have reduced the pauses between application operations during garbage collection, which has resulted in improved performance.

Garbage Collector Request Methods

After we make an object garbage collection eligible, the garbage collector might not destroy it immediately. JVM destroys only objects when it runs the Garbage Collector program.

Alternatively, we can ask the JVM to run Garbage Collector. You can do it with two different ways:

  • By using System.gc() method: There is a static method gc() in the System class that requests the JVM to run the Garbage Collector.
  • By using Runtime.getRuntime().gc() method:Application code can use the Runtime class to interact with the JVM. In this way, we can request a garbage collector to run in the JVM by calling its gc() method.

A Garbage Collector will not always run when either of the above two methods gets used. Runtime.getRuntime().gc () is equivalent to System.gc().gc()

Benefits

Garbage collectors provide the following benefits:

  • It eliminates the need for developers to release memory manually.
  • Manages the heap efficiently by allocating objects.
  • Keeps memory available for future allocations by reclaiming objects that are no longer in use. It saves constructors time and energy by not having to initialize every data field of managed objects.
  • A memory safety function ensures that objects can't use another object's memory for their own use.

Code

The following code will demonstrate how you can perform Garbage collection in java.

package garbageCollectionSampleProgram;
public class InitGC {
public static void main(String[] args)
{
  long m1, m2, m3;
    Runtime rt = Runtime.getRuntime();
    for(int i = 0; i < 3; i++)
    {
m1 = rt.freeMemory();
createObjects(300);
m2 = rt.freeMemory();
System.gc();
m3 = rt.freeMemory();
System.out.println("m1 = " + m1 + ", m2 = " + m2 + ", m3 = " +m3 + "\nMemory freed by gc() =  " + (m3 - m2));
System.out.println("-------------------------");
    }
  }
public static void createObjects(int count)
{
for(int i = 0; i < count; i++)
{
    new Object();
  }
}
}

Output

m1 = 254741016, m2 = 254741016, m3 = 257150048

Memory freed by gc() =  2409032-------------------------

m1 = 255807848, m2 = 255807848, m3 = 257149952

Memory freed by gc() =  1342104-------------------------

m1 = 255807704, m2 = 255807704, m3 = 257149952

Memory freed by gc() =  1342248-------------------------

write your code here: Coding Playground