HotSpot ships a no-op garbage collector, Epsilon (-XX:+UseEpsilonGC), which allocates memory but never reclaims it. What is it actually for?
answer
- Allocates, never reclaims; OOM on exhaustion
- Needs -XX:+UnlockExperimentalVMOptions
- Control group: measure the app without collector interference
- Allocation-regression tests: OOM instead of silent slowdown
- Never for long-running services
basics
~20 sEpsilon allocates and never collects; when the heap is exhausted the JVM exits with an OutOfMemoryError. It exists for performance testing where GC must be excluded, for measuring an application's true allocation footprint, for last-drop latency experiments, and for very short-lived processes that finish before the heap fills.
solid answer
~60 sEpsilon is a fully functional allocator with no reclamation at all. Objects are handed out until the heap is exhausted, at which point the JVM throws `OutOfMemoryError` and (typically configured to) terminate. Its uses are diagnostic and specialised: - **Performance testing without GC noise.** Benchmarking a data structure or a hot path with GC completely removed isolates the code's own cost from collector interference. - **Measuring allocation footprint.** Run a workload to completion under Epsilon with a known heap and you learn exactly how much memory it allocated in total — a number no other collector exposes so plainly. - **Latency experiments.** Establishing the floor: how fast is this path with zero GC overhead, including barriers? - **Regression testing for allocation.** A test that must not allocate beyond a budget fails loudly under a sized Epsilon heap. - **Extremely short-lived processes** — a CLI or a lambda-style task that finishes before it exhausts the heap — where paying for any collector is waste. It requires `-XX:+UnlockExperimentalVMOptions`. It is not a production strategy for ordinary services: any long-running application will exhaust the heap and die.
go deeper
Know it allocates without ever collecting and that the JVM dies when the heap fills.
Name the concrete uses — benchmarking without GC interference, allocation-footprint measurement, very short-lived processes — and why it is not a production choice.
Use it deliberately as a control in collector comparisons and as an allocation-regression guard in tests.
Frame it as the measurement baseline that makes collector cost an argued number rather than an opinion when setting fleet policy.
## The idea Epsilon (JDK 11 onward, behind `-XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC`) implements the collector interface but performs no collection. It handles allocation — including thread-local allocation buffers — and does nothing else. When the heap is exhausted it does the only thing left: reports `OutOfMemoryError` and, with the usual `-XX:+ExitOnOutOfMemoryError` or a heap dump flag, ends the process. At first hearing this sounds like a joke flag. It is a serious engineering tool, for a reason worth understanding: **a control group**. Every other collector entangles application behaviour with collector behaviour — barriers on reference stores, concurrent threads consuming CPU, pauses interrupting measurement. Epsilon removes that entanglement so you can measure the application alone. ## The real uses **Isolating GC from a benchmark.** When you measure two implementations of a data structure and one allocates more, GC cost contaminates the comparison in ways that depend on heap size and collector heuristics. Under Epsilon there is no collector, so the measurement is of the code. You then re-measure under the production collector to learn what the allocation *costs* — the difference between the two runs is precisely the GC tax of that design. **Measuring total allocation footprint.** Give Epsilon a known heap, run the workload, and observe whether it completes and how much heap it consumed. This turns "how much does this job allocate?" into an experiment with a crisp answer, without an allocation profiler attached. **Allocation-regression tests.** A latency-critical path that is supposed to be allocation-free can be exercised in a test JVM with Epsilon and a small heap: if a refactor introduces allocation, the test dies with `OutOfMemoryError` rather than quietly getting slower. This is a strong, blunt guard rail. **Establishing a latency floor.** Comparing a path under Epsilon against the same path under G1 or ZGC quantifies the barrier and pause overhead the production collector imposes — useful when arguing about collector choice with numbers instead of adjectives. **Genuinely short-lived processes.** A batch task, a CLI tool, or a function-style workload with a bounded, known allocation total can run to completion before the heap fills. Skipping collection entirely saves the barrier overhead and all collector CPU. This use is narrow and needs a *proved* bound on total allocation, plus a heap sized with margin, because the failure mode is termination. **JVM development.** It is also the baseline against which collector interface changes and other collectors are evaluated. ## Where it does not belong Any long-running service. "We'll just give it a huge heap" fails, because allocation is unbounded over time: a service allocating a modest 100 MB/s exhausts a 1 TB heap in under three hours. Epsilon is not a low-latency trick for production, and proposing it as one signals a misunderstanding of what it is. ## How to talk about it The interviewer is checking whether you understand that a collector is a *cost* as well as a service, and that isolating that cost is a legitimate experimental technique. The concise answer is: no-op allocator, dies on heap exhaustion, used for benchmarking without GC, allocation-footprint measurement, allocation-regression tests, latency floors, and very short-lived processes — never for a long-running service.
- Could you run a production web service under Epsilon by giving it an enormous heap?No. Allocation in a long-running service is unbounded over time, so any finite heap is exhausted eventually — even a terabyte lasts only hours at a modest hundred megabytes per second. Epsilon's terminal state is OutOfMemoryError, so this converts a tuning problem into a scheduled crash.
- How does Epsilon help you decide between collectors?It gives you the zero-GC baseline. Running the same workload under Epsilon and under the candidate collectors quantifies exactly what each collector costs in throughput and latency for your code, including barrier overhead that never appears in GC logs. Adjective-level arguments about collectors become a table of numbers.
saying these in an interview costs you the question
- Treating Epsilon as a production low-latency option for a long-running service.
- Believing it makes the JVM allocation-free or somehow avoids OutOfMemoryError.
- Not knowing it needs the experimental-options unlock and so claiming it is unavailable.
- Confusing it with the Serial collector, which does collect, just with one thread.