Java provides several types of garbage collectors, each designed for different kinds of applications with varying performance requirements. These garbage collectors manage memory by reclaiming unused objects and free heap space, but they differ in how they prioritize factors such as throughput, pause times, and heap size. Below are the main types of garbage collectors available in Java:
1. Serial Garbage Collector (Single-Threaded GC)
The Serial Garbage Collector is the simplest and oldest garbage collector in Java. It performs all garbage collection (GC) operations using a single thread, making it suitable for small applications or environments where there is only one processor core.
How it works:
- Young Generation Collection (Minor GC): Single-threaded, stop-the-world garbage collection is performed in the young generation.
- Old Generation Collection (Major GC): Also single-threaded and stop-the-world.
Use cases:
- Best suited for small applications with small heap sizes (up to a few hundred MB) or applications running on single-core CPUs.
- Not recommended for modern, large-scale, or multi-threaded applications.
Command to enable:
1 |
-XX:+UseSerialGC |
2. Parallel Garbage Collector (Throughput Collector)
The Parallel Garbage Collector, also known as the Throughput GC, is designed to maximize application throughput by using multiple threads for garbage collection.
How it works:
- Young Generation Collection (Minor GC): Multiple threads are used to perform garbage collection in the young generation.
- Old Generation Collection (Major GC): Similarly, multiple threads are used to collect the old generation.
- Its main goal is to achieve high throughput by maximizing the amount of time the application spends executing code, minimizing the time spent in garbage collection.
Use cases:
- Suitable for multi-threaded applications that require high throughput and can tolerate longer pause times.
- Works well with medium to large heap sizes.
- Not ideal for applications requiring low-latency or real-time processing.
Command to enable:
1 |
-XX:+UseParallelGC |
You can also specify the desired number of GC threads:
1 |
-XX:ParallelGCThreads=<n> |
3. Concurrent Mark-Sweep (CMS) Garbage Collector
The CMS (Concurrent Mark-Sweep) garbage collector is designed for applications that require low-latency garbage collection with minimal pauses. CMS focuses on reducing the stop-the-world (STW) pause times by performing most of its work concurrently with the application’s execution.
How it works:
- Young Generation Collection: Uses the Parallel GC for young generation collection (similar to the Parallel GC).
- Old Generation Collection: Performs most of its garbage collection in the old generation concurrently with the application’s threads, meaning it minimizes the stop-the-world pauses.
- CMS uses a mark-sweep algorithm that marks live objects and then sweeps away dead objects.
Use cases:
- Suitable for low-latency applications like web servers, where quick response times are more important than maximizing throughput.
- CMS is often used in interactive applications that cannot afford long pauses for GC.
- Works best with medium to large heap sizes.
Limitations:
- CMS does not compact the heap (except in certain situations), which can lead to fragmentation.
- Can fail if fragmentation prevents allocating large objects.
Command to enable:
1 |
-XX:+UseConcMarkSweepGC |
4. G1 (Garbage-First) Garbage Collector
The G1 GC is a low-latency, region-based garbage collector designed to replace CMS. It is the default GC in Java 9 and later and is particularly well-suited for applications with large heaps and low-latency requirements.
How it works:
- G1 divides the heap into regions and focuses on collecting regions with the most garbage first (hence "Garbage-First").
- Performs both young generation and old generation collections.
- G1 is designed to achieve predictable pause times and balance between throughput and low-latency by adjusting how many regions it collects at a time.
- Supports parallel and concurrent phases.
Use cases:
- Suitable for applications requiring low-pause times and high throughput.
- Works well for large heap sizes (hundreds of GB) and is designed for server-side applications.
- Commonly used in enterprise, web servers, microservices, and real-time processing systems.
Command to enable:
It is the default in Java 9 and later, but if needed explicitly:
1 |
-XX:+UseG1GC |
You can also set the target maximum pause time:
1 |
-XX:MaxGCPauseMillis=<n> |
5. Z Garbage Collector (ZGC)
The Z Garbage Collector (ZGC) is a scalable low-latency garbage collector introduced in Java 11. It aims to keep pause times below 10ms, regardless of heap size, and is designed for applications that need large heap sizes (up to multi-terabytes). ZGC is designed for environments with a large memory footprint but requires minimal pause times.
How it works:
- ZGC uses a mark-compact algorithm that performs most of its operations concurrently with the application’s threads.
- It divides the heap into small regions, allowing it to manage memory efficiently without long pauses.
- Concurrent garbage collection ensures that pauses are kept to a minimum (typically < 10 ms) regardless of the heap size.
Use cases:
- Suitable for applications that need to manage large heaps and require low-latency garbage collection.
- Best for real-time applications, high-performance systems, or applications with multi-terabyte heap sizes.
- Often used in big data systems, high-frequency trading, and low-latency financial systems.
Command to enable:
1 |
-XX:+UseZGC |
6. Shenandoah Garbage Collector
Shenandoah is another low-pause garbage collector introduced by Red Hat and available in OpenJDK from Java 12 onwards. Like ZGC, Shenandoah aims to minimize pause times, but it uses different techniques.
How it works:
- Shenandoah performs concurrent compaction of the heap (unlike CMS) to minimize fragmentation.
- It divides the heap into regions and uses concurrent garbage collection to ensure very low pause times, regardless of heap size.
- It compacts the heap concurrently with the application, keeping stop-the-world (STW) pauses short.
Use cases:
- Ideal for large heap sizes and low-latency applications.
- Similar to ZGC, Shenandoah is designed for low-latency systems that cannot afford long GC pauses.
- Useful in applications with multi-terabyte heap sizes and real-time processing requirements.
Command to enable:
1 |
-XX:+UseShenandoahGC |
Comparison of Java Garbage Collectors
Garbage Collector | Heap Size | Pause Time | Throughput | Latency | Concurrent Phases |
---|---|---|---|---|---|
Serial GC | Small | High | High for small apps | Low | No |
Parallel GC | Medium to Large | High | High | Low (not low-latency) | No |
CMS GC | Medium to Large | Medium | Medium | Low | Yes |
G1 GC | Medium to Large | Low (predictable) | Medium to High | Low | Yes |
ZGC | Large to Huge | Very Low (< 10ms) | High | Very Low | Yes |
Shenandoah GC | Large to Huge | Very Low (< 10ms) | Medium to High | Very Low | Yes |
How to Choose the Right Garbage Collector for Your Application
-
Serial GC: Use for small applications with small heap sizes where throughput matters more than pause times (e.g., simple batch jobs).
-
Parallel GC: Ideal for high-throughput applications where throughput is the primary goal and pause times are not critical (e.g., batch processing).
-
CMS GC: Suitable for low-latency applications that require shorter GC pauses but can tolerate some fragmentation (e.g., web servers, real-time systems).
-
G1 GC: Best for medium to large applications needing a balance between pause times and throughput, with predictable pause times (e.g., enterprise apps, large web services).
-
ZGC: Use for very large heap sizes (up to terabytes) and low-latency applications requiring minimal pause times (e.g., big data, high-performance computing).
-
Shenandoah: Similar to ZGC, best for large heap sizes and applications requiring **extremely
low-latency and low pause times** (e.g., real-time analytics, financial services).
Each garbage collector has its strengths and weaknesses, and the choice depends on your application’s specific needs for latency, throughput, and heap size.