Skip to content
Back
JVM internals

How to Choose a JVM Garbage Collector

Why most objects die young, the three dimensions every collector trades off, and a quick guide to picking the right one for your workload.

Michał Artur Marciniak

2 min read

On this page
  1. Prologue: The Symphony of Memory
  2. The Generational Hypothesis - The Rhythm of Object Lifetimes
  3. Choosing Your Conductor - The Decision Matrix

“The garbage collector is the invisible conductor of your application’s memory symphony. Choose the wrong maestro, and your performance hits dissonance; choose wisely, and even terabytes of data flow in perfect harmony.”


Prologue: The Symphony of Memory

Imagine your JVM application as a grand orchestra performing a complex symphony. The musicians are your objects - strings, brass, woodwinds, percussion - each playing their part in the performance. The garbage collector is the conductor, ensuring that when a musician’s part ends, they exit gracefully, making room for new performers without disrupting the music.

The JVM offers multiple garbage collectors because no single conductor suits every venue. Allocation rates, object lifespans, heap sizes - this memory patterns determine which collector will keep your performance in tune.

Most developers ignore GC until the music stops. Then they’re frantically searching for why their application hit pause times longer than a Mahler symphony. Master your GC choice now, and you’ll never face that 2 AM fire drill.

2026 JVM Reality Check:

  • Java 25 LTS released September 2025 - current production standard
  • G1 is the default for server-class machines (Java 9+) - but defaults aren’t always optimal
  • ZGC is generational by default since Java 23 - -XX:+ZGenerational flag deprecated
  • Non-generational ZGC removed in Java 24 (JEP 490) - any -XX:-ZGenerational flags will now cause startup failure
  • Generational Shenandoah (JEP 521) added in Java 25
  • Shenandoah delivers sub-millisecond pauses independent of heap size
  • Parallel GC still dominates throughput-focused batch processing
  • CMS is deprecated and removed - don’t build new systems on it
  • Containerized environments demand GC tuning more than ever

Related: Learn about Java 25’s silent revolution - Project Leyden, Generational Shenandoah, and how modern JVM features can yield significant performance gains with minimal code changes.


The Generational Hypothesis - The Rhythm of Object Lifetimes

Most Objects Die Young

Before understanding specific collectors, grasp this fundamental truth: the vast majority of objects live brief, intense lives. Like fireflies that flash brightly for a moment and fade, temporary objects - request handlers, calculation intermediates, StringBuilder instances - sparkle into existence and disappear almost immediately.

This observation is the weak generational hypothesis, and it shapes every modern JVM garbage collector.

The heap is divided into two arenas:

  • Young Generation: The nursery where new objects are born. Here, objects either mature quickly or perish in the first collection. Minor collections here are frequent but lightning-fast because most objects are already dead.
  • Old Generation: The hall of survivors. Objects that endure multiple young collections earn tenure here. Full collections in this space are rare but more expensive.
The life of an object on the heapState with 6 nodes and 6 connectionsAllocatedMinor GCSurvivedNext GCSurvived N timesMajor GCNew objectNew objectEdenEdenSurvivorSurvivorOld generationOld generationCollectedCollectedCollectedCollected
  1. New object
  2. ↓ AllocatedEdenMinor GC → Collected
  3. ↓ SurvivedSurvivor↻ Next GC
  4. ↓ Survived N timesOld generation
  5. ↓ Major GCCollected
Most objects die in Eden at their first minor GC. The few that survive move between the two survivor spaces and, after enough collections, into the old generation.

The JVM leverages this lifecycle pattern. Young generation collections (minor GC) happen often but quickly because they’re filled with garbage. Old generation collections (major/full GC) happen rarely but take longer because live data accumulates there.

The Three Performance Dimensions

Every GC decision balances three competing priorities:

  • Throughput

    Total work done per unit of time.

    Matters forBatch processing, data pipelines

  • Latency

    Pause times during collection.

    Matters forWeb services, trading systems, games

  • Footprint

    Memory overhead of the GC itself.

    Matters forResource-constrained containers

Parallelpauses up to seconds
G1pauses of 20–200 ms
ZGCpauses under 10 ms
0 s1 s2 s
The same two seconds of a service under three collectors. Each violet block is a stop-the-world pause: the service answers no request while it lasts. An illustration, not a measurement.

You cannot optimize all three simultaneously. Choose your priority, and the collector choice becomes clear.


Choosing Your Conductor - The Decision Matrix

Quick Selection Guide

Choosing a garbage collectorFlowchart with 5 nodes and 4 connectionsThroughputLatencyFootprintBalanceWhat matters most?What matters most?ParallelParallelZGC or ShenandoahZGC or ShenandoahSerialSerialG1, the defaultG1, the default

What matters most?

  • ThroughputParallel
  • LatencyZGC or Shenandoah
  • FootprintSerial
  • BalanceG1, the default
Pick the priority from the three dimensions above. When none of them dominates, stay with G1.

Two more facts narrow the choice. Above 16 GB of heap, only ZGC and Shenandoah keep pauses short. Shenandoah ships with OpenJDK builds such as Red Hat and Temurin, but not with Oracle JDK.

Collector Comparison

SerialParallelG1ZGCShenandoahPausesLong, stop-the-worldLong, sometimes secondsTarget 200 ms by defaultUnder 10 ms at any heap sizeUnder 10 ms at any heap sizeThroughputModerateVery highHighAt most 15% overheadSlightly higher than ZGCHeapUp to 100 MB4 GB and up4–16 GBUp to 16 TBUp to 16 TBBest forOne core, embedded systemsBatch, ETLGeneral purposeLow-latency servicesLow latency, containers