JEP 189: Shenandoah: A Low-Pause-Time Garbage Collector (Experimental)

AuthorsChristine H. Flood, Roman Kennke
OwnerRoman Kennke
StatusClosed / Delivered
Componenthotspot / gc
Discussionhotspot dash gc dash dev at openjdk dot java dot net
Reviewed byAleksey Shipilev, Andrew Dinn, Erik Österlund
Endorsed byVladimir Kozlov
Created2014/01/02 20:00
Updated2021/08/28 00:15


Add a new garbage collection (GC) algorithm named Shenandoah which reduces GC pause times by doing evacuation work concurrently with the running Java threads. Pause times with Shenandoah are independent of heap size, meaning you will have the same consistent pause times whether your heap is 200 MB or 200 GB.


This is not the one GC to rule them all. There are other garbage collection algorithms which prioritize throughput or memory footprint over responsiveness. Shenandoah is an appropriate algorithm for applications which value responsiveness and predictable short pauses. The goal is not to fix all JVM pause issues. Pause times due to reasons other than GC like Time To Safe Point (TTSP) issues or monitor inflation are outside the scope of this JEP.

Success Metrics

This project will be a success if we can keep consistent short gc pause times.


Modern machines have more memory and more processors than ever before. Service Level Agreement (SLA) applications guarantee response times of 10-500ms. In order to meet the lower end of that goal we need garbage collection algorithms which are efficient enough to allow programs to run in the available memory, but also optimized to never interrupt the running program for more than a handful of milliseconds. Shenandoah is an open-source low-pause time collector for OpenJDK designed to move us closer to those goals.

Shenandoah trades concurrent cpu cycles and space for pause time improvements. We've added an indirection pointer to every Java object which enables the GC threads to compact the heap while the Java threads are running. Marking and compacting are performed concurrently so we only need to pause the Java threads long enough to scan the thread stacks to find and update the roots of the object graph.

The Shenandoah algorithm is described in depth in this PPPJ2016 paper.

Shenandoah has been implemented and will be supported by Red Hat for aarch64 and for amd64.

The on-going development for Shenandoah is done in the OpenJDK Shenandoah project. See more details on current development flow, implementation details, availability at Shenandoah wiki page.


Zing/Azul has a pauseless collector, however that work has not been contributed to OpenJDK.

ZGC has a low pause collector based on colored pointers. We look forward to comparing the performance of the two strategies.

G1 does some parallel and concurrent work, but it does not do concurrent evacuation.

CMS does concurrent marking, but it performs young generation copying at pause times, and never compacts the old generation. This results in more time spent managing free space in the old generation as well as fragmentation issues.

Building and Invoking

As experimental feature, Shenandoah will require -XX:+UnlockExperimentalVMOptions in the command line. The Shenandoah build system disables the build on unsupported configurations automatically. Downstream builders may choose to disable building Shenandoah with --with-jvm-features=-shenandoahgc on otherwise supported platforms.

To enable/use Shenandoah GC, the following JVM options will be needed: -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC.

Please see the Shenandoah wiki page for more information on how to setup and tune Shenandoah GC.


Red Hat has done extensive testing for our important applications. We've developed many Shenandoah specific jtreg tests. Shenandoah is shipping in Fedora starting with Fedora 24 and as a tech preview in Rhel 7.4. Running standard OpenJDK testing with -XX:+UseShenandoahGC should be sufficient.

Risks and Assumptions

The GC interface (JEP 304) was integrated in JDK 11, and many extensions and improvements have been made to the GC interface since. This minimizes the risks of adding Shenanodah to the OpenJDK source base. In addition to that, any Shenandoah-specific code paths that cannot reasonably be addressed will be guarded by #ifdef INCLUDE_SHENANDOAHGC or similar mechanisms. Shenandoah GC will initially be marked as an experimental feature and thus require -XX:+UnlockExperimentalVMOptions in addition to -XX:+UseShenandoahGC.