Shenandoah GC



Reviewing here about Concurrent GC’s and GC’s strategy, I saw about Shenandoah GC quite interesting topic. The phases are basically related to marking the regions. Basically in summary:

Concurrent → the application runs together with the GC
Regional based GC – Forwarding pointers enable Shenandoah to collect each region independently without remembered sets.
Not generational based (this means the log does not have Young, Tenure, Old) → don’t look for young gen on the logs and .
Shenandoah compacts concurrently –> CMS :/

Operates in 3 or 2 concurrent phases (deprecated traversal operates in one concurrent mode)

OpenJDK versions

In regards to the OpenJDK versions, it can be used in OpenJDK 1.8 & OpenJDK 11 & OpenJDK 17 (update 2021). Targeting for pauses below 10ms (Similar to ZGC Oracle – soft goal).

Shenandoah GC

Basically, Shenandoah is about regional collection – if this sentence makes sense.  It has 9 phases but also 5 heuristics. The paper can be accessed here (paper describes Shenandoah1 not Shenandoah2).

The usage is pretty simple: just use the flag: XX:+UseShenandoahGC

The phases are enumerated below: 

   Concurrent Marking

   Concurrent Evacuation

   Concurrent Update References

Failure Modes

Basically Shenandoah is a run to clean more memory than the application is generating – a concurrent GC. But sometime you start to lose this race, so then first you start to clean everything but still with the threads running, and if still does not work, so then you stop everything to clean the heap. So then Pacing –> Degenerative –> Full GC/STW.

Pacing: First it will pace the application allocation →  up to a certain ShenandoahPacingMaxDelay (default max is 10ms)

Degenerative GC ~ STW occurs together with the concurrent cycle. It can turn to Full GC if the concurrent gc do not happen (if a failure is detected after some phase) → yes 

Full GC/ STW – Finally as the last resource it can be used to avoid an OOME – which can be the case for ZGC. Stop everything, including the concurrent threads, and clean the heap.


Basically will define when the GC should happen, as in the heuristic will decide to start GC cycle on certain heap occupancy.

Static heuristic ~ First then if we set a goal, as in a hard set percentage, like 50%, and stick with that . But this can be too pessimistic, meaning you clean too much in advance from the actual application usage  == heap occupancy.

Adaptive heuristic ~ still used ~ It sets some boundaries but adapts according to the application usage of the memory. There are three options in case the application is filling faster than cleaning.

The heuristics can be used as:


And tells the GC how to actually start the mechanism. They are: adaptative, static, compact, passive and aggressive.

Reddit thread

Shenandoah Visualizer

It is possible to use the Shenandoah visualizer tool to understand more about it.


Youtube Video from Christine Flood

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s