Why you want to run Java 10 if you're using the G1 Garbage Collector

Richard Warburton & Sadiq Jaffer

Java 10 will be available at a download site near you on 20th March 2018. Given that date is rapidly approaching it’s a good time to start thinking about what features will be included. While the headline feature of the release is greater type-inference there’s also a lot of exciting stuff going on under the hood. One of the changes that may benefit people the most is a big improvement to The G1 Garbage Collector’s worst case pause times. So if you want to learn more about that, then read on.

G1

G1 became the default Garbage Collector in Java 9 after being included with the JDK since Java 7. The key idea behind the G1 GC is to split the heap up into different regions. Each region contains objects of a similar generation: either Eden, Survivor or Tenured. Whilst G1 collects all the young generational regions in one go, it will only collect the regions that it believes to have the most dead objects in from its tenured regions. This is why it’s called the Garbage First or G1 collector. By controlling how many regions it collects it can time-slice its pauses and try to not pause your application longer than a given pause goal. Collections that only collect the young generational regions are called “Young GCs” and collections that collect both young and tenured regions are called “Mixed GCs”.

If you’re interested in more information on how G1 works there are many articles, answers, a book and talks. This blog post isn’t focusing on the overall approach to how G1 works but on the changes in Java 10.

Full GC Pauses in G1

G1 has been constantly tweaked and improved since it first made it into the JDK, ensuring that it’s a stable GC for people to use and improving its performance. One of the big problems remaining in G1 is that it can still result in occasional lengthy GC pauses. The longest GC pauses are caused by Full GCs: Garbage Collections that collect every region in the G1 heap. Full GCs can be triggered when normal mixed GCs are unable to keep up with the allocation rate or when humongous objects (objects over 50% of the size of a region) can’t be allocated due to a lack of space.

Java 10 reduces Full GC pause times by iteratively improving on its existing algorithm. Until Java 10 G1 Full GCs ran in a single thread. That’s right - your 32 core server and it’s 128GB will stop and pause until a single thread takes out the garbage. In Java 10 this has been improved to run in Parallel. This means that the Full GCs will be on multiple threads in parallel, albeit still pausing the JVM’s progress whilst it completes. The number of threads can be optionally configured using -XX:ParallelGCThreads.

This is a nice improvement to the G1 algorithm in Java 10 that should reduce worst case pause times for most users. Does that mean that Java GC pauses are a thing of the past? No - it reduces the problem but since G1 doesn’t run its collection cycles concurrently with your application it will still pause the application periodically and Full GC pauses still increase with larger heap sizes. We’ve talked about some other Garbage Collectors in our last blog post that may solve this problem in future.


Related articles