Backend Development 6 min read

Upgrading to JDK 17 with ZGC: Performance Comparison and Migration Guide

This article explains why upgrading to JDK 17 and switching to the low‑latency ZGC garbage collector can dramatically reduce pause times and improve throughput, compares GC and CPU metrics against G1, and provides step‑by‑step installation and JVM tuning instructions with code examples.

Architecture Digest
Architecture Digest
Architecture Digest
Upgrading to JDK 17 with ZGC: Performance Comparison and Migration Guide

The pause times of traditional garbage collectors such as CMS and G1 are a major pain point for latency‑sensitive services, often reaching tens or hundreds of milliseconds. ZGC, introduced experimentally in JDK 11 and production‑ready since JDK 15, aims to solve this by offering sub‑10 ms pauses and supporting heap sizes from 8 MB to 16 TB.

1.1 Irrefutable reasons to upgrade to JDK 17 include the need for millisecond‑level GC latency, better Spring Boot support, JIT improvements, new language features (sealed classes, pattern matching, records), and enhanced security patches.

1.2 Applicable scenarios are gateway services and Web APIs, while batch jobs, scheduled tasks, and CPU‑intensive workloads are not recommended.

2.1 GC time comparison shows ZGC achieving sub‑1 ms pauses compared to the much longer pauses of CMS, Parallel GC, and G1, as illustrated by the included chart.

2.2 CPU usage comparison indicates that the same workload on JDK 17 consumes about 10‑20 % more CPU than on JDK 8.

2. Upgrade method

3.1 Installing JDK 17

# ubuntu install jdk17
sudo apt install openjdk-17-jdk

# docker base images
docker pull openjdk:17-slim
docker pull openjdk:17-jdk-oraclelinux7
FROM openjdk:17-slim

3.2 JVM parameter adjustments for ZGC

--add-opens=java.base/java.lang=ALL-UNNAMED \
-Xms1500m -Xmx1500m \
-XX:ReservedCodeCacheSize=256m \
-XX:InitialCodeCacheSize=256m \
-XX:+UnlockExperimentalVMOptions \
-XX:+UseZGC \
-XX:ConcGCThreads=1 -XX:ParallelGCThreads=2 \
-XX:ZCollectionInterval=30 -XX:ZAllocationSpikeTolerance=5 \
-XX:+UnlockDiagnosticVMOptions -XX:-ZProactive \
-Xlog:safepoint,classhisto*=trace,age*,gc*=info:file=/opt/gc-%t.log:time,tid,tags:filecount=5,filesize=50m \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:HeapDumpPath=/opt/errorDump.hprof

For comparison, the G1 configuration used was:

-Xmx3500m -Xms3500m -XX:+UseG1GC -XX:MaxGCPauseMillis=100
-XX:G1ReservePercent=10 -XX:ConcGCThreads=2 -XX:ParallelGCThreads=5
-XX:G1HeapRegionSize=16m -XX:MaxTenuringThreshold=14
-XX:SurvivorRatio=8

Both configurations were tested on a production machine handling 1500 TPS. The results demonstrate that ZGC can keep JVM‑level pauses under 1 ms, which is essential for low‑latency requirements.

References: https://tech.meituan.com/2020/08/06/new-zgc-practice-in-meituan.html https://tech.dewu.com/article?id=59

backendJavaJVMGarbage CollectionZGCperformance tuningjdk17
Architecture Digest
Written by

Architecture Digest

Focusing on Java backend development, covering application architecture from top-tier internet companies (high availability, high performance, high stability), big data, machine learning, Java architecture, and other popular fields.

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.