Garbage Collection in Java is the process where the JVM automatically manages memory by removing unused objects from the heap. This not only optimizes memory usage but also prevents memory leaks and reduces application crashes. By understanding the types of Garbage Collection in Java, how each works, and the best practices to follow, developers can build high-performance applications that efficiently handle memory without manual cleanup. This guide will help you understand all the key concepts of memory management in Java in detail.
Table of Contents:
What is Garbage Collection in Java?
Garbage Collection (GC) in Java is the process of automatically removing objects by the JVM that are no longer needed by a program, to free up memory and avoid memory leaks. The JVM allocates the memory for new objects on the heap when the unused objects are no longer needed. It prevents memory leaks and enhances the performance of the system. Java handles memory management itself, unlike other programming languages like C or C++.
In Java, the objects are created in heap memory, but when the object is no longer needed, the garbage collector reclaims that memory, which allows the application to use heap memory efficiently. If a garbage collector in Java is not present, then the heap will get filled up with the unused objects, which will cause an OutOfMemoryError.
Master Java Today - Accelerate Your Future
Enroll Now and Transform Your Future
Need for Garbage Collection in Java
In Java, garbage collection is needed to automatically manage memory by restoring the space occupied by objects that are not used by any part of the program. GC helps to prevent memory leaks and also ensures the heap is used efficiently. It also reduces the chances of application crashes due to OutOfMemory exceptions and allows developers to focus on writing logic without explicitly freeing the unused memory.
How Does Garbage Collection Work in Java?
The JVM in Java works by automatically identifying and removing the unused objects that are no longer needed by a program. Now, let us discuss the working of Garbage Collection in Java.
1. Object Creation
When an object is created in Java using the new keyword. The JVM allocates memory for this object in the memory. The heap memory is used to store all objects and class instances during the execution of a program. This object will remain in the memory until it is used by any of the programs.
2. GC Roots
GC Roots are the entry points in memory where the object traversal starts. To determine whether an object is in use or not, the JVM performs a reachability analysis starting from GC Roots, which gives a reference to all the objects that are directly or indirectly linked to a program.
Note: If an object is accessible from any GC Root, it is considered reachable and will not be collected.
3. Unreachable Objects
After the GC has completed the reachability analysis, any object that is not reachable from a GC Root is considered unreachable and is eligible for garbage collection. This object will not be destroyed immediately, but it will be marked as a candidate for garbage collection.
4. Mark and Sweep
In this process, the GC starts from the GC roots and deletes all the objects that are not in use by any of the running programs. This phase improves the availability of the system and prevents memory leaks by ensuring that objects are not present in the memory.
In the above image, the mark phase is started, where the garbage collector starts from root references (like local variables and static fields) and marks all reachable objects, shown in blue, as alive. In the sweep phase, it scans the heap and removes the unmarked (unreachable) objects, shown in red, thereby freeing up memory.
Types of Events in Java Garbage Collection
The heap in Java is divided into 2 generations to manage the memory efficiently. Java has different types of events based on what part of the memory (heap) is being cleaned and what kind of garbage collector is in use. Some of the events in Garbage Collection in Java are as follows.
1. Minor or Young GC
Minor Garbage Collection is the process of cleaning the memory in the Young Part of the Java heap. It is called Minor because it affects only a small portion of the heap, and new objects of the program are created in this generation. The Minor GC is also further divided into the following parts.
- Eden Space: This is the place where all the new objects are created using the new keyword, and objects in this place live and die quickly.
- Survivor Space 0 (S0) and Survivor Space 1 (S1): This place holds the object that survived one or more Minor GCs.
The Minor GC comes into play when the Eden place becomes full. It pauses the application for a very short time, and the reachable objects in Eden space are identified, which are moved to Survivor Space, and the unreachable objects in Eden are collected and removed.
2. Major GC or Old Generation GC
The Major GC refers to the process of cleaning the memory of the long-lived objects that have survived the Minor GC, and stores the objects, like caches. It comes into play when there is no space available for the Young Generation, then the methods like System.gc() or Runtime.getRuntime().gc() are used to explicitly clean the garbage in the memory.
3. Full GC
The Full GC occurs in the entire heap, i.e., Young + Old Gen + sometimes in Metaspace also. It completely cleans the memory, including class loading and unreachable objects. The method system.gc() is explicitly called in the programs.
4. Permanent Generation
Permanent generation was a part of the Java Heap before Java 8, which was used to store metadata about classes, like static variables, annotations, class names, methods, and so on. It is different from the Young and Old generations. It was removed after Java 8 because it has a fixed size and does not support the dynamic loading of classes in complex applications.
Note: In Java 8+, Permanent Generation was replaced with Metaspace.
How Can an Object Be Unreferenced?
Below are some key concepts on Garbage Collection that can be used to make an object unreferenced.
1. Unreachable Objects
In Java, an object becomes unreachable when there are no more references to it from any part of the application, i.e., the program cannot use or access it. These unreachable objects can be used for garbage collection.
For example,
public class UnreachableExample {
public static void main(String[] args) {
MyClass obj = new MyClass(); // Object is referenced
obj = null; // Now unreachable
}
}
In this example, the obj holds a reference to a MyClass object, and by setting the obj=null removes the reference to it, due to which it becomes eligible for GC.
2. Requesting Garbage Collection
In Java, garbage collection is done automatically, but you can also request to manually collect the garbage and reclaim the memory by using
- System.gc(): This is a static method provided by the System class to request the JVM to perform the garbage collection.
System.gc();
It internally calls the Runtime.getRuntime().gc() method.
- Runtime.getRuntime().gc(): This is a non-static method that works on the singleton instance of the Runtime class.
Runtime.getRuntime().gc()
3. Object Created Inside a Method
When an object is created inside a method, it becomes a local object and its reference is stored in the Stack. When the execution of the method is finished, the stack frame is removed from, and the reference to the object is lost, which makes it eligible for garbage collection.
For example,
public class MethodObjectExample {
public static void main(String[] args) {
create(); // Object created inside this method
}
public static void create() {
MyClass obj = new MyClass(); // Object is referenced here
System.out.println("Inside method: " + obj);
}
}
In the above example, obj is a local variable inside the create method, which points to a MyClass object. When the create method finishes, it works; the stack frame is destroyed. Hence, no reference to object obj1, due to which it becomes unreachable.
4. The finalize() Method
The finalize() method in Java is a special type of method used to perform cleanup operations before an object is garbage collected. It belongs to the Object class, which can be overridden to perform operations, like closing a file or releasing a resource when it is free.
protected void finalize() throws Throwable {
// cleanup code
}
Note: The finalize() method is deprecated in Java 9+ and removed in Java 18.
5. Nullifying a Reference
Nullifying a reference means explicitly assigning the null value to an object reference, which will make the value of an object null, and once the object becomes unreachable, it becomes eligible for garbage collection. Sometimes, in big applications, it helps to remove references to large objects that are no longer needed.
For example,
public class NullifyExample {
public static void main(String[] args) {
MyClass obj = new MyClass(); // Object created and referenced
obj = null; // Reference is nullified
// Hint to JVM to run GC
System.gc();
}
}
In the above example, the object obj of MyClass is created, and after its usage, its value is set to null, which is helpful for the garbage collection to clean up the memory.
6. Assigning a Reference to Another
If you assign a reference variable to a new object, the old object it referred to becomes unreferenced if no other variable refers to it.
For example,
MyClass obj1 = new MyClass(); // obj1 refers to object A
obj1 = new MyClass(); // object A is now unreferenced
In this example, the object of MyClass obj1 is created, and then it is unreferenced by making its new object using the new keyword.
7. Using an Anonymous Object
An anonymous object is an object that is created without being assigned to a reference variable, due to which its memory is immediately cleaned after its usage. These objects are temporary and are used when the object has to be used only once.
For example,
public class AnonymousObjectExample {
public static void main(String[] args) {
new MyClass(); // Anonymous object created
System.gc(); // Request garbage collection
}
}
In the above example, the object of MyClass does not have a variable, hence it is an anonymous object.
What is the OutOfMemoryError in Java?
java.lang.OutOfMemoryError is a runtime error in Java that occurs when the JVM cannot allocate memory to create new objects, which means that your application has used the available memory resources, either in the heap, stack, or any memory area. The OutOfMemoryError in Java can occur when the heap memory is full, too much is spent in GC, creation of too many threads, infinite loops, and so on.
Example:
Output:
Explanation: In the above Java program, the size of the ArrayList list is increasing until the memory of the compiler is reached to a certain limit, due to which it throws java.lang.OutOfMemoryError.
Get 100% Hike!
Master Most in Demand Skills Now!
Types of Garbage Collection in Java
Below are the types of garbage collections in Java.
1. Serial Garbage Collector
Serial Garbage Collector is the simplest GC algorithm provided by the JVM. It is designed for a single-threaded environment and stops all the running applications when it runs. It is suitable for small applications or embedded applications where the memory and CPU usage are limited.
To enable the serial garbage collector, you can use the following command:
java -XX:+UseSerialGC -Xmx128m -Xms128m MyApp
In the above example, the java -XX:+UseSerialGC command enables the serial garbage collector. MyApp is the name of the application, and 128m stands for 128MB.
2. Parallel Garbage Collector
Parallel Garbage Collector, also known as Throughput Collector, is used to maximize the throughput of an application by using multiple threads for garbage collection. It is suitable for high-performance applications that run on multiple processors, where throughput is the main criterion instead of application pause time.
To enable the parallel garbage collector, you can use the following command:
java -XX:+UseParallelGC -Xms512m -Xmx512m MyApp
In the above example, the java -XX:+UseParallelGC command enables the parallel garbage collector. MyApp is the name of the application, and 512m stands for 512MB.
3. CMS (Concurrent Mark Sweep) Garbage Collector
The CMS garbage collector was designed to minimize the pause time of the application by running multiple threads of an application concurrently. It is suitable for a real-time application where the application cannot be put on hold for a long time.
To enable the CMS garbage collector, you can use the following command:
java -XX:+UseConcMarkSweepGC -Xms512m -Xmx512m MyApp
In the above example, the java -XX:+UseConcMarkSweepGC command enables the CMS garbage collector. MyApp is the name of the application, and 512m stands for 512MB.
Note: CMS is removed in Java 14.
4. G1 (Garbage First) Garbage Collector
The G1 GC is a server-style and region-based garbage collector introduced in Java 7 and was made the default garbage collector from Java 9 onwards. It was designed with the motive to decrease pause time and increase the performance of the application of large heap applications. It divides the heap into regions with concurrent performance.
To enable the G1 GC garbage collector, you can use the following command:
java -XX:+UseG1GC -Xms2g -Xmx2g -XX:MaxGCPauseMillis=200 MyApp
In the above example, the java -XX:+UseG1GC command enables the G1 GC garbage collector, and MyApp is the name of the application. It also sets the pause time to 200ms, but it does not guarantee that it will meet this pause time or not.
5. Z Garbage Collector (ZGC)
The Z garbage collector was introduced by Oracle in JDK 11, and made production-ready in JDK 15. to handle very large heap sizes (up to terabytes) with a pause time under 10ms, irrespective of the heap size. It was mainly designed for scalability and performance, making the application ideal for real-world requirements like trading systems.
To enable the ZGC garbage collector, you can use the following command:
java -XX:+UseZGC -Xmx4G MyApp
In the above example, the java -XX:+UseZGC command enables the ZGC, and MyApp is the name of the application. The 4G stands for 4GB, i.e., the heap size will never grow more than 4GB.
6. Shenandoah Garbage Collector
Shenandoah is a concurrent garbage collector introduced by Red Hat and was available from the JDK 12. Its main goal was to minimize the GC pause times, irrespective of heap size.
To enable the Shenandoah garbage collector, you can use the following command:
java -XX:+UseShenandoahGC MyApp
In the above example, the java -XX:+UseShenandoahGC command enables the Shenandoah, and MyApp is the name of the application.
Project Management System Using Garbage Collection in Java
Problem Statement:
Suppose you are an intern at a software company like Intellipaat, and you are told to write a program to count the number of projects currently active in the company (excluding completed or archived projects). To make this program, you have to use the concept of a Garbage Collector.
Actual Task You Were Given:
Write a program to create a class called Project having the following data members:
- An ID for storing a unique ID allocated to every project.
- Name of the project.
- Duration of the project in months.
Also, provide the following methods:
- A parameterized constructor to initialize the name and duration of the project.
- The ID should be initialized, and the total count of active projects should be updated here in the constructor.
- A method show() to display the ID, name, and duration of the project.
- A method showNextId() to display the ID of the next project.
- A method showActiveProjects() to display the current number of projects
- A method to reduce the project count when a project object is destroyed by the Garbage Collector.
Code:
Output:
Explanation: The above Java program defines a Project class with a constructor Project(String name, int durationMonths) to initialize project details, assign a unique ID, and update the active project count. The show() method displays the ID, name, and duration of the project, while showNextId() shows the next ID of the project. The showActiveProjects() method displays the number of active projects in the system. The finalize() method is called by the Garbage Collector to decrease the count of the active project when a project object is destroyed. In the main() method, the objects of the projects are created, their details are displayed, and some references are set to null before calling System.gc() to trigger garbage collection.
Advantages of Garbage Collection
Below are the advantages of Garbage Collection in Java.
- Automatic memory management: In some languages, like C and C++, the user has to manually release the memory when they have used an object, but in the case of Java, the GC automatically finds unused objects in the memory and releases them.
- Avoids memory leaks: Memory leaks happen when the memory is still occupied by the objects that are no longer in use. In Java, the GC helps to prevent this by removing the objects that no longer have a reference to any used program.
- Improves program stability: Manually freeing up memory can lead to bugs like double frees (freeing the same memory twice), GC prevents these issues and makes the program safe and less prone to crashes.
- Saves development time: Developers don’t need to write any extra code to clean up memory, hence they can focus on writing the application code, hence, saving their time.
- Optimizes memory usage: GC reuses the unused space from the available memory to use it for other programs.
Disadvantages of Garbage Collection
Below are the disadvantages of Garbage Collection in Java.
- Performance overhead: While cleaning the memory, GC uses the CPU time and resources, which can affect your application’s performance, especially if memory is managed poorly.
- Needs more memory to work well: The GC works better when there is enough memory available in the Heap, but if there is not enough memory in the Heap. The GC will have to run more frequently to free up space, and these frequent runs can slow down your application.
- Unpredictable pauses: Sometimes, Java stops your program to clean its memory; this interruption can also occur at critical tasks, like gaming, hence it will be problematic.
- No control over when cleanup happens: In other languages like C++, you can control when to free up memory, but in Java, the GC chooses the time to clean up memory, which can be problematic if you are doing an important task like a database connection or network connections.
- Slower cleanup with large memory: If your program uses a large part of the memory, the Garbage Collector might take longer to scan and clean it up, causing slowdowns.
Java Garbage Collection Best Practices
Below are the best practices you should follow while performing garbage collection in Java.
- Minimize the object creation: To minimize the object creation, you can reuse the already built objects, like using StringBuilder instead of String.
- Avoid memory leaks: Memory leaks in Java happen when a used object cannot be referenced by the running program. To avoid memory leaks, you can remove the reference from the collection by using the static analysis tools.
- Use weak references for caching: Java has multiple reference types, i.e., strong, weak, soft, or phantom. By using WeakHashMap for caches, the garbage collector can reclaim the memory when it is needed.
- Use finalizers and cleaners carefully: In Java, the finalize() method was used to clean up resources, like closing the file, but it was deprecated due to its performance issues. Hence, use it wisely.
- Monitor and tune garbage collection: Regularly monitor your application’s garbage collection to optimize performance by using tools like JVisualVM, GC logs, or Java Mission Control.
Unlock Your Future in Java
Start Your Java Journey for Free Today
Conclusion
From the above article, we learned that garbage collection in Java is used for memory management and automatically removes unused objects. There are many types of garbage collection in Java: Serial, Parallel, CMS, G1, and so on. They help you to understand how the JVM manages memory, optimizes performance, and minimizes application pauses by cleaning unused objects efficiently. It has both its advantages and disadvantages, and should be used wisely by following the best practices.
Garbage Collection in Java – FAQs
Q1. What is garbage collection in Java?
Garbage Collection in Java is a process where the unused objects from memory are removed automatically, which frees up heap space, prevents memory leaks, and improves application stability without manual memory management.
Q2. What are the types of garbage collection in Java?
The main types of Garbage Collection in Java are Serial, Parallel, CMS, G1, ZGC, and Shenandoah.
Q3. Why does Java need a garbage collector?
Java needs a garbage collector to automatically free memory used by objects that are no longer referenced, which ensures efficient memory usage, prevents memory leaks, and reduces the risk of OutOfMemoryError.
Q4. What is the finalize in Java?
The finalize() method in Java was used to perform cleanup before an object was garbage collected. However, it is deprecated from Java 9 onwards due to performance issues.
Q5. How to resolve long garbage collection time?
To reduce long garbage collection times, you can tune JVM parameters, choose the right type of garbage collection in Java (e.g., G1 or ZGC for low pauses), minimize unnecessary object creation, and monitor GC performance using tools like JVisualVM or GC logs.
Q6. Can you force garbage collection in Java?
You can request garbage collection in Java by calling System.gc() or Runtime.getRuntime().gc() methods.
Q7. What happens if garbage collection fails in Java?
If garbage collection fails to free enough memory, the JVM will throw a java.lang.OutOfMemoryError, which means that your application is using more memory than allocated or has a memory leak.
Q8. Is garbage collection in Java predictable?
Garbage Collection in Java is not fully predictable because the JVM decides when to run it based on memory needs.