Maksim Kabakou - Fotolia

How to use Epsilon GC to stop Java garbage collection

The best way to stop Java garbage collection from happening is to use the experimental Epsilon GC, no-op garbage collector from JDK 11. Learn how and when to use it.

You can't force garbage collection in Java. There are some strategies you can use to get the Java virtual machine to prioritize the task, but the indeterminate nature of garbage collection means the process can't be forced.

Similarly, you can't stop Java garbage collection from happening, either. You can change some configuration settings in the Java virtual machine (JVM) that impact the variables that trigger garbage collection (GC) routines, but you can't completely stop Java GC from happening. Or can you?

Epsilon GC, also known as Java's no-op garbage collector, provides memory allocation facilities but it doesn't do any memory reclamation. Epsilon GC doesn't just prevent Java garbage collection from happening -- it eliminates GC altogether.

Epsilon GC is an experimental feature released with JDK 11. To start an application or microservice on a JVM with Epsilon GC enabled, include the following JVM options:

-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

Epsilon GC JVM args
Special switches must be provided at runtime to use the experimental no-op garbage collector.

Pros and cons of Epsilon GC

So, what's so great about Epsilon GC? DevOps professionals who deploy applications and microservices to JVM with it get the lowest memory management latency.

The drawback? When the JVM reaches the limits of its allocated memory, it will crash and burn with an OutOfMemoryError, terminating the JVM. Once the Java heap is exhausted, no further object allocations are possible. And since no memory reclamation is allowed, the JVM will fail with an OutOfMemoryError written to the logs and a heap dump written to the file system.

When to use Epsilon GC

Why would anyone want to use a Java memory management tool whose normal operation has the potential to terminate the JVM? There are a few valid use cases for Epsilon GC, including:

  • performance testing routines where GC routines skew the gathered metrics;
  • extremely short-lived routines where the JVM is terminated on exit;
  • for ultra-latency sensitive applications where the memory footprint is well-established;
  • for garbage-free applications that perform primarily iterative and conditional logic;
  • for highly clustered Java-based microservice deployments on Kubernetes where intermittent JVM failures are unlikely to cause a service degradation; and
  • for servers that allocate immense quantities of memory at startup and then cycle down at the end of the workday.

A common use case for Epsilon GC is the determination of optimal memory management settings for the JVM. To determine the best Java heap size settings for an application, an application can be tested under load with the no-op garbage collector turned on. Profiling tools like Java Flight Recorder and JDK Mission Control can then be used to determine optimal Xms and Xmx settings for the minimum and maximum heap sizes. This approach generates performance metrics that are untainted with the additional overhead required to perform memory reclamations.

JFR and JMC memory tools
Java Flight Recorder and JDK Mission Control can be used to determine optimal memory management settings.

When developers and DevOps professionals inquire about the ability to stop the JVM, they typically want to delay it for 10 or 15 minutes so they can avoid a stop-the-world event during critical service windows. Unfortunately, there is no such command, API or JDK utility that will temporarily pause Java GC.

The closest option available is to take advantage of Epsilon GC, JEP-318, and turn off GC completely. Then, build a Java memory management strategy that builds around the inevitable heap dump and OutOfMemoryError that will occur if object creations exceed the amount of memory allocated to the heap.

Dig Deeper on Development tools for continuous software delivery