Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Garbage Collectors Overview

DZone's Guide to

Garbage Collectors Overview

In this article, we give an overview of the types of garbage collectors available in the current version of HotSpot JVM, and what each is designed to do.

· Performance Zone ·
Free Resource

Maintain Application Performance with real-time monitoring and instrumentation for any application. Learn More!

The current version of HotSpot JVM includes three types of garbage collectors:

  • Serial Collector

  • Parallel Collector

  • The Mostly Concurrent Collectors

All of them are generational ones, meaning that they take advantage of the way the heap is divided.

There are three main operations which the garbage collector is responsible for:

  • Finding objects which are no longer used.

  • Freeing up the memory after those objects.

  • Compacting the heap.

Not all the collectors perform those operations in the same way, so let's go through the basic information about all of them. We will cover details in separate articles. 

Serial Collector

As the name suggests, the collection is performed by only one thread. Stop-the-world (STW) pauses are necessary during both Minor and Full GC. 

This collector uses the mark-copy algorithm for the Young Generation, whereas the Old Generation is cleaned up using the mark-sweep-compact algorithm.

Serial GC is designed for single-threaded environments (usually client-class machines) and for relatively small heaps. It can be enabled by -XX:+UseSerialGC flag.

Parallel (Throughput) Collector

The Young collection is parallelized by multiple threads which makes Minor GC much faster. As a result, this collector leads to shorter, but more frequent Young collection STW pauses. Since JDK 7u4, the Old Generation is also collected by multiple threads by default (and also causes stop-the-world pauses). Prior to JDK 7u4, the -XX:+UseParallelOldGC flag was required to enable parallel processing of the Old Generation. Now, both -XX:+UseParallelGC and -XX:+UseParallelOldGC flags enable Throughput Collector with parallel processing of both the Old and Young Generations.

This collector also uses the mark-copy algorithm in the Young Generation and mark-sweep-compact in the Old Generation, but both copy and compact phases are executed by multiple threads.

To configure the number of GC threads you can use the -XX:ParallelGCThreads=X flag. The default value is set to the number of CPU cores.

When is Parallel GC a good choice? Well, basically whenever throughput is more important than latency.

The Mostly Concurrent Collectors

They are so called low pause collectors - designed to minimize stop-the-world pauses and to keep the application as responsive as possible

Concurrent Mark and Sweep (CMS)

Minor GC is performed with multiple threads using the parallel mark-copy algorithm. All application threads are stopped then. The Old Generation is mostly collected concurrently - application threads are paused for very short periods of time when the background GC thread scans the Old Generation. The actual algorithm used during Major GC is concurrent mark-sweep. As you probably noticed, there is no "compact" after "sweep." That's true - Concurrent Mark and Sweep is the collector which doesn't compact the Tenured space and thus the memory can be left fragmented. Due to lack of heap compaction, when GC is not able to fit new objects into the memory, JVM fallbacks to the serial mark-sweep-compact algorithm to defragment and compact the Old Generation. That's when performance degradation comes into play - all application threads are stopped and just one single thread is responsible for cleaning and compacting the Tenured space. 

As I mentioned earlier, CMS is an example of low pause collectors. It means that it's a good choice when latency is the primary target, not throughput - because throughput can be degraded due to increased CPU consumption (scanning the heap when application threads are running isn't for free).

-XX:+UseConcMarkSweepGC enables the CMS collector. It used to be possible to configure CMS with a single-threaded Young Generation collection using -XX:-UseParNewGC (notice minus before "UseParNewGC," so by using this flag we disable Parallel New (Young) GC), but it was deprecated in Java 8 and removed in Java 9.

G1GC

Garbage First (G1) is a new low-pause garbage collector designed to process large heaps with minimal pauses. The heap is broken down into several regions of fixed size (while still maintaining the generational nature of the heap). That kind of design allows us to get rid of long STW pauses when the entire Young or Old Generations are processed. Now, each region can be collected separately which leads to shorter, but more frequent STW pauses. G1 copies objects from one region into another, which means that the heap is at least partially compacted.

G1 uses an incremental version of the mark-sweep-compact algorithm. It can be enabled by specifying the -XX:+UseG1GC flag. 

Summary

Here is a simple comparison of the collectors discussed in this article:

Collector

Multiple GC Threads

STW (Young Generation)

STW (Old Generation)

Heap Compaction

Primary Goal

Serial no yes yes yes -
Parallel yes yes yes yes

throughput

CMS yes yes

only during scan

no latency
G1 yes yes

very short ones

partially latency


There are some other garbage collectors out there, but they are not part of HotSpot JVM. These are:

  • C4 (Azul Zing JVM)

  • Shenandoah

  • Balanced (IBM J9 JVM)

In Java 8, a default GC for server-class machines is Parallel Collector. G1GC is going to be the default one in Java 9. Client-class machines run Serial Collector by default.

Collect, analyze, and visualize performance data from mobile to mainframe with AutoPilot APM. Learn More!

Topics:
heap ,garbage colection ,throughput ,performance ,jvm

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}