Learnitweb

Epsilon: A No-Op Garbage Collector

1. Introduction

In Java 11, a No-Op Garbage Collector called Epsilon was introduced which handles memory allocation but does not implement any actual memory reclamation mechanism. When the Java heap limit is exhausted, the JVM terminates. Epsilon garbage collector promises lowest possible GC overhead.

2. Enabling Epsilon GC

Epsilon GC can be enabled using
-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC

“epsilon” frequently means “empty symbol”, which is aligned with the no-op nature of this GC. The epsilon GC does not do any GC cycles. Once the Java heap limit is exhausted, no allocation and memory reclamation is possible and therefore JVM shuts down.

3. Example

To try Epsilon GC, first we need an application.

public class EpsilonDemo {

    public static void main(String[] args) {

        final int GIGABYTE = 1024 * 1024 * 1024;
        final int ITERATIONS = 100;

        System.out.println("Starting program...");

        // allocate memory 1GB at a time
        for (int i = 0; i < ITERATIONS; i++) {
            var array = new byte[GIGABYTE];
        }

        System.out.println("Completed successfully");
    }
}

When you run the program with Epsilon, You’ll get something like this:

Starting program...
Terminating due to java.lang.OutOfMemoryError: Java heap space

4. Use cases for no-op garbage collector

  • Performance testing: Having a no-op garbage collector provides a useful tool to compare the performance of other garbage collectors when used in the application. This helps in validating various artifacts such as performance of garbage collector, GC workers scheduling etc.
  • Memory pressure testing: Having a no-op GC, allows to test the allocated memory threshold.
  • Extremely short lived jobs: If a job is extremely short lived, resulting in cleaning up of resources in the end on exit, using the GC to clean up of heap space is a waste. No-op GC is a good option in this scenario.
  • Latency improvements: For latency sensitive applications, where we no exactly the memory footprint, a long GC cycle may not be desired. In such cases a no-op GC can be helpful.
  • Throughput improvements: All OpenJDK GCs are generational (with exceptions of non-mainline Shenandoah and ZGC), and they emit at least one reference write barrier. Avoiding this barrier can bring the last bit of throughput improvement.

5. Conclusion

In conclusion, the Epsilon garbage collector presents a fascinating approach to memory management in Java, offering a lightweight, no-op solution for environments where garbage collection overhead is not a concern or where memory allocation patterns are predictable. While it may not be suitable for every use case, its existence expands the toolkit available to Java developers, providing another option for tailoring memory management strategies to specific application requirements.