JDK-8359802 : JEP 523: Make G1 the Default Garbage Collector in All Environments
  • Type: JEP
  • Component: hotspot
  • Sub-Component: gc
  • Priority: P4
  • Status: Candidate
  • Resolution: Unresolved
  • Submitted: 2025-06-17
  • Updated: 2025-09-09
Related Reports
Relates :  
Relates :  
Relates :  
Relates :  
Description
Summary
-------

Make the Garbage-First (G1) garbage collector the default collector in all environments, rather than just server environments.

Goals
-----

When no garbage collector is specified on the command line:

* The HotSpot JVM will always select G1.

* In scenarios in which the JVM previously selected the [Serial](https://docs.oracle.com/en/java/javase/24/gctuning/available-collectors.html#GUID-45794DA6-AB96-4856-A96D-FDE5F7DEE498) collector, the performance metrics of throughput, latency, memory footprint, and startup time should not degrade significantly.

## Non-Goals

It is not a goal to:

* Prohibit future changes of the default garbage collector. As typical application profiles change and collector performance evolves, the default collector should be re-evaluated.

* Interfere with user selection: A collector chosen explicitly will always override the JVM’s selection.

* Deprecate or remove any existing collector.

* Change the functionality or behavior of G1.

## Motivation

The HotSpot Java Virtual Machine (JVM) provides automatic dynamic memory management, i.e., garbage collection, which continuously identifies and removes unused objects, freeing memory to be reused by the application. This allows developers to write code without worrying about memory management. Garbage collection improves productivity since it eliminates many classes of application errors related to memory management.

Different applications have different requirements on the performance metrics of throughput, latency, footprint, and startup time. The JVM therefore includes multiple garbage collectors, each of which focuses on different combinations of these metrics. For example, [ZGC] prioritizes latency and [Parallel] prioritizes throughput, while [G1] is designed to balance latency and throughput. If you know which collector is best for your application then you can specify it when you start the JVM; otherwise, the JVM will select one for you.

[ZGC]: https://docs.oracle.com/en/java/javase/24/gctuning/z-garbage-collector.html#GUID-8637B158-4F35-4E2D-8E7B-9DAEF15BB3CD
[Parallel]: https://docs.oracle.com/en/java/javase/24/gctuning/parallel-collector1.html#GUID-DCDD6E46-0406-41D1-AB49-FB96A50EB9CE
[G1]: https://docs.oracle.com/en/java/javase/24/gctuning/garbage-first-g1-garbage-collector1.html#GUID-ED3AB6D3-FD9B-4447-9EDF-983ED2F7A573

We made G1 the default collector for server environments in JDK 9 ([JEP 248](https://openjdk.org/jeps/248)). At that time, testing showed that Serial had significant advantages in throughput and footprint in constrained environments with a single CPU and less than 1.8 GB of heap. We therefore adjusted the JVM's GC selection algorithm to choose Serial in such environments.

Since then, we have improved the G1 collector across all metrics, and testing shows that G1 is now competitive with Serial at all heap sizes. With our recent work to reduce synchronization ([JEP 522](https://openjdk.org/jeps/522)), G1's maximum throughput is close to that of Serial. G1's maximum latencies have always been better than those of Serial, since G1 reclaims memory in the old generation via [incremental garbage collections](https://docs.oracle.com/en/java/javase/24/gctuning/garbage-first-g1-garbage-collector1.html#JSGCT-GUID-F1BE86FA-3EDC-4D4F-BDB4-4B044AD83180) rather than full collections. Finally, in recent releases we have reduced G1's native memory usage to levels comparable to that of Serial.

G1's performance is now sufficient to replace Serial in all situations in which the JVM would previously have selected Serial. It is time to stop selecting Serial by default in constrained environments. This will also make it easier to understand and reason about the JVM’s behavior.

## Description

If you do not specify a garbage collector on the command line then the JVM will always select G1, regardless of the number of processors and the Java heap size.

## Testing

This change only affects JVM performance metrics in constrained environments. Therefore, we will thoroughly performance-test G1 and compare it with Serial on a wide variety of workloads in such environments. There should be no significant differences in performance.

## Risks and Assumptions

It is possible that some applications in constrained environments will still perform best with Serial. In such cases, you can still select Serial explicitly.

Comments
I've reviewed this and think it's ready for the next step in the JEP process.
23-07-2025

>> I think JDK build script/makefiles also use Serial GC. Will you switch it to G1 too? > That has not been decided yet, and is separate from this change - I will investigate the difference. In my measurements on a fairly beefy machine, a full product build with G1 instead of Serial GC is equal. Building the JDK seems most sensitive to VM startup time, and GCs are equal here (and GC startup is not the issue, and probably has not been for a long time). In any case I think this change should not be part of this JEP. Here're some user/sys/cpu/total times: with current G1: useg1gc-regular.build.log:make CONF=-r images 4799.51s user 349.61s system 2084% cpu 4:07.03 total useg1gc-regular.build.log:make CONF=-r images 4804.86s user 350.13s system 2092% cpu 4:06.36 total useg1gc-regular.build.log:make CONF=-r images 4801.26s user 350.32s system 2063% cpu 4:09.61 total useg1gc-regular.build.log:make CONF=-r images 4808.67s user 350.84s system 2086% cpu 4:07.26 total useg1gc-regular.build.log:make CONF=-r images 4811.76s user 350.55s system 2080% cpu 4:08.15 total useg1gc-regular.build.log:make CONF=-r images 4811.91s user 351.88s system 2082% cpu 4:07.95 total useg1gc-regular.build.log:make CONF=-r images 4803.10s user 350.64s system 2100% cpu 4:05.31 total useg1gc-regular.build.log:make CONF=-r images 4795.91s user 349.78s system 2104% cpu 4:04.47 total useg1gc-regular.build.log:make CONF=-r images 4791.90s user 349.34s system 2095% cpu 4:05.30 total useg1gc-regular.build.log:make CONF=-r images 4798.05s user 349.41s system 2098% cpu 4:05.24 total with serial gc: useserial.build.log:make CONF=-r images 4805.07s user 350.10s system 2075% cpu 4:08.37 total useserial.build.log:make CONF=-r images 4805.74s user 347.99s system 2091% cpu 4:06.44 total useserial.build.log:make CONF=-r images 4799.57s user 348.67s system 2088% cpu 4:06.55 total useserial.build.log:make CONF=-r images 4803.65s user 349.02s system 2086% cpu 4:06.96 total useserial.build.log:make CONF=-r images 4804.01s user 348.84s system 2085% cpu 4:07.08 total useserial.build.log:make CONF=-r images 4802.18s user 348.18s system 2090% cpu 4:06.31 total useserial.build.log:make CONF=-r images 4802.26s user 349.10s system 2086% cpu 4:06.86 total useserial.build.log:make CONF=-r images 4813.82s user 348.73s system 2042% cpu 4:12.70 total useserial.build.log:make CONF=-r images 4810.10s user 349.37s system 2083% cpu 4:07.64 total useserial.build.log:make CONF=-r images 4809.56s user 349.77s system 2075% cpu 4:08.54 total Seems very much equal to me (note that user and sys time are also about the same, not only total time).
23-07-2025

Fwiw, the patch for these tests was something like this, ie. I grepped the make directory for UseSerialGC and replaced the occurrences with UseG1GC: diff --git a/make/RunTestsPrebuiltSpec.gmk b/make/RunTestsPrebuiltSpec.gmk index 03c877a4277..136123670dc 100644 --- a/make/RunTestsPrebuiltSpec.gmk +++ b/make/RunTestsPrebuiltSpec.gmk @@ -64,7 +64,7 @@ TEST_JOBS ?= 0 # Use hard-coded values for java flags (one size, fits all!) JAVA_FLAGS := -Duser.language=en -Duser.country=US JAVA_FLAGS_BIG := -Xms64M -Xmx2048M -JAVA_FLAGS_SMALL := -XX:+UseSerialGC -Xms32M -Xmx512M -XX:TieredStopAtLevel=1 +JAVA_FLAGS_SMALL := -XX:+UseG1GC -Xms32M -Xmx512M -XX:TieredStopAtLevel=1 BUILDJDK_JAVA_FLAGS_SMALL := -Xms32M -Xmx512M -XX:TieredStopAtLevel=1 BUILD_JAVA_FLAGS := $(JAVA_FLAGS_BIG) diff --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4 index feb16c7d179..4edec2bd629 100644 --- a/make/autoconf/boot-jdk.m4 +++ b/make/autoconf/boot-jdk.m4 @@ -510,7 +510,7 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], AC_MSG_CHECKING([flags for boot jdk java command for small workloads]) # Use serial gc for small short lived tools if possible - UTIL_ADD_JVM_ARG_IF_OK([-XX:+UseSerialGC],boot_jdk_jvmargs_small,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-XX:+UseG1GC],boot_jdk_jvmargs_small,[$JAVA]) UTIL_ADD_JVM_ARG_IF_OK([-Xms32M],boot_jdk_jvmargs_small,[$JAVA]) UTIL_ADD_JVM_ARG_IF_OK([-Xmx512M],boot_jdk_jvmargs_small,[$JAVA]) UTIL_ADD_JVM_ARG_IF_OK([-XX:TieredStopAtLevel=1],boot_jdk_jvmargs_small,[$JAVA])
23-07-2025

> Different applications have different requirements on the performance metrics throughput, latency, footprint and startup behavior. Add the word "of" after metrics. So it reads ".... metrics of throughput, latency, ..." > According to JEP 248 ergonomics currently typically selects G1 if the user did not specify a different garbage collector on the command line. Change to say: "Since JDK9, ergonomics typically selects G1...". Using by "currently" and "typically" together is unnecessary if the JDK release sets the timeframe. > At that time we implemented an exception in the ergonomics for these situations and have ergonomics choose the Serial collector as the garbage collection algorithm. Change to say: "An exception was implemented in the ergonomics to instead choose the Serial collector for these constrained environments." > So we believe that current G1 garbage collector performance is sufficient to replace the Serial collector in all situations ergonomics would have selected it before. Change to say: "G1's performance is sufficient to replace the Serial collector in all situations ergonomics would have selected it before. It's time to remove the ergonomics exception for constrained environments".
22-07-2025

Okay
07-07-2025

> I think JDK build script/makefiles also use Serial GC. Will you switch it to G1 too? That has not been decided yet, and is separate from this change - I will investigate the difference.
04-07-2025

I think JDK build script/makefiles also use Serial GC. Will you switch it to G1 too?
03-07-2025