Backend Development 9 min read

JDK 21 Garbage Collection Benchmarks: G1, Parallel & Generational ZGC

This article compares JDK 8, 17, and 21 using SPECjbb®2015 to evaluate throughput, latency, and memory consumption of G1, Parallel, and generational ZGC, highlighting significant performance gains and offering upgrade guidance for Java applications.

Java Architecture Diary
Java Architecture Diary
Java Architecture Diary
JDK 21 Garbage Collection Benchmarks: G1, Parallel & Generational ZGC

Several years after the original article on JDK 8 and JDK 17 garbage collectors, JDK 21 LTS provides new benchmarks and features such as virtual threads, pattern‑matching switch statements, and generational ZGC. The following sections examine their performance.

1. Introduction

Comparing JDK versions is difficult, but overall Java platform performance has improved markedly since JDK 8. This article uses SPECjbb®2015, a well‑known benchmark, to show gains via two scores: max‑jOPS (raw throughput) and critical‑jOPS (throughput under latency constraints). Benchmarks run with a fixed 16 GB heap, large pages enabled, and pre‑paging to reflect out‑of‑the‑box behavior.

2. Choosing GC

Oracle supports four garbage collectors; Serial GC is omitted because it is unsuitable for this benchmark. The three collectors compared are:

G1 GC – default since JDK 9, balances latency and throughput.

Parallel GC – throughput‑oriented, may incur longer pauses.

ZGC – ultra‑low‑latency, fully concurrent with sub‑millisecond pauses.

The choice depends on application priorities; no single collector excels in every scenario.

3. Progress

Since JDK 8, G1 and Parallel have seen major improvements: shorter pauses, lower memory usage, and higher throughput. ZGC now offers a generational mode, which is the focus of this analysis. The charts compare G1 and Parallel across JDK 8, 17, 21, and ZGC (including generational ZGC) across JDK 17 and 21.

3.1 Throughput

Raw throughput gains since JDK 17 are modest, but the gap between JDK 8 and newer releases is significant, especially for G1 and Parallel. Generational ZGC adds roughly a 10 % improvement.

3.2 Latency

Latency scores show similar trends; the best results appear in JDK 21. Generational ZGC demonstrates noticeable latency reduction compared to legacy ZGC, though pause lengths remain sub‑millisecond. Most of the gain comes from improved throughput scores.

3.3 Memory Usage

Peak native memory consumption shows Parallel remains stable, while G1 has become the most memory‑efficient collector after JDK 20 reduced its marking bitmap. Generational ZGC trades higher native memory for better latency and throughput, but overall memory consumption can be lower because it allows smaller heaps.

4. Upgrading and Trying Generational ZGC

If you are still on JDK 8, consider upgrading to JDK 21 and re‑evaluate your GC choice. To enable generational ZGC in JDK 21, add the following JVM flags:

<code>-XX:+UseZGC
-XX:+ZGenerational
</code>

The ultimate goal is to move away from legacy mode and gather feedback on cases where generational ZGC underperforms.

5. Translator’s Note

The translator notes that for most services G1 is sufficient, while memory‑intensive workloads such as Kafka or RocketMQ may benefit from ZGC or generational ZGC.

JavaGarbage CollectionPerformance BenchmarkJDKGenerational ZGC
Java Architecture Diary
Written by

Java Architecture Diary

Committed to sharing original, high‑quality technical articles; no fluff or promotional content.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.