For most Java server workloads without strict pause-time requirements, start with the JVM’s default collector—G1 in Oracle JDK 25—and measure before changing it. Consider ZGC or Shenandoah when application tail latency makes pauses a demonstrated problem and you can afford the CPU and memory headroom their concurrent work requires. None is a universal winner, and G1’s pause-time target is not a guarantee.
How G1, ZGC, and Shenandoah differ
| Collector | Design and goal | Tradeoffs and a sensible starting point |
|---|---|---|
| G1 | Generational and region-based. It combines concurrent work with stop-the-world pauses, evacuating live objects from selected regions. In Oracle JDK 25 it is the server-class default and targets a balance between pause behavior and throughput. | Concurrent work consumes CPU, and large or humongous allocations, marking pressure, and evacuation problems can affect pauses. A practical hypothesis is to begin with the runtime default for a conventional server workload, then use GC logs and measurements to decide whether tuning is warranted. |
| ZGC | A concurrent low-latency collector. Oracle’s Java SE 25 command reference says pause times are independent of heap size and documents supported heap sizes from 8 MB to 16 TB. | Its low-pause design has a throughput cost; concurrent cycles use CPU and need enough free heap for allocations while collection runs. Test it when tail latency is a priority, particularly with a large heap, while measuring CPU, throughput, and memory headroom. |
| Shenandoah | OpenJDK describes concurrent marking and compaction, so pause times are not directly proportional to heap size. Current command documentation distinguishes single-generation satb and generational modes. |
Availability and supported modes depend on the JDK vendor and build. Concurrent work also needs CPU and allocation headroom. Test it only after confirming support in the deployed build, and compare it under the same workload and resource limits as alternatives. |
These are design goals and starting hypotheses, not predictions of application response time. GC pauses are only one contributor to latency, and there is no established universal benchmark winner across workloads.
As an Amazon Associate I earn from qualifying purchases.
What G1’s pause-time goal actually means
G1 divides the heap into regions, tracks promising collection candidates, and evacuates live objects from selected regions. Some collection work is concurrent; other operations, including evacuation, occur during pauses. Its adaptive policy tries to meet pause goals with high probability over time, rather than guaranteeing a maximum duration for each pause. Oracle explicitly says G1 is not a real-time collector in its Java SE 25 G1 guide.
Recommended Free Tools
Oracle documents -XX:MaxGCPauseMillis with a default target of 200 ms in its Java SE 25 java command reference. That is a soft goal, not a promise that every pause will be 200 ms or shorter. A target can influence the latency-throughput balance, but it cannot make G1 suitable for hard real-time deadlines.
Oracle’s G1 guide discusses workloads with heaps into tens of gigabytes or larger, substantial live sets, variable allocation or promotion, fragmentation, and pause targets of a few hundred milliseconds. This is workload guidance, not a minimum heap size or a rule that smaller heaps should avoid G1. Oracle’s broader collector-selection guidance emphasizes that the best choice depends on heap size, live data, and processor availability.
What low-pause concurrent collection trades
ZGC: low pauses across heap sizes, with resource costs
Oracle’s Java SE 25 command reference characterizes ZGC as a low-latency collector with pauses of a few milliseconds “at some throughput cost,” and says pause times are independent of heap size. It also lists a supported heap range of 8 MB to 16 TB. These are statements in Oracle’s JDK 25 documentation, not guarantees of zero pauses, identical behavior across vendors, or equal application performance for every workload.
Rank #2
Because collection proceeds concurrently with application work, ZGC uses processor time while the application runs. The heap must also accommodate the live set and leave room for allocations during collection. If CPU is constrained or allocation bursts consume that room faster than collection can reclaim it, the low-pause design may not deliver the desired end-to-end result.
Shenandoah: concurrent compaction, subject to build support
OpenJDK’s Shenandoah project documentation describes reducing pauses by doing more work concurrently, including compaction, so pause times are no longer directly proportional to heap size. The current OpenJDK command-line documentation identifies satb as single-generation and generational as generational. The command documentation is on the moving OpenJDK main branch, so verify the options against the exact JDK release and vendor build you deploy.
Do not assume Shenandoah is present, or that a particular mode is supported, merely because a different JDK includes it. Confirm the actual runtime’s collector availability and accepted flags before planning a rollout.
Choose based on the workload, not the collector label
- Start with G1 when pause needs are not strict and you want a sensible default for a typical server workload. Oracle recommends starting with the VM default unless pause requirements are strict.
- Evaluate ZGC or Shenandoah when measured application tail latency points to GC pauses as a meaningful problem, and lower pause sensitivity is worth testing against CPU and memory costs.
- Compare ZGC and Shenandoah on your own build only after verifying availability and mode support; the available evidence does not establish a universal vendor matrix or performance winner.
- Keep the whole service in view: low GC pause times do not by themselves ensure low p95, p99, or p99.9 application latency.
Run a fair collector comparison
A comparison is useful only if collector choice is the main changed variable. Keep the JDK build, machine or container limits, application version, data set, heap settings, warm-up, and load profile consistent across runs. Capture GC logs alongside application-level latency.
Rank #4
Compare these measures rather than relying on averages or a single pause figure:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problems- Application p95, p99, and p99.9 latency, plus the distribution of GC pauses.
- Throughput under a fixed resource budget.
- CPU used by GC and concurrent threads.
- Live-set size, heap occupancy, allocation rate, and remaining allocation headroom.
- Pause frequency and total time spent in collection.
- Stability during bursts, high promotion, and memory pressure.
- Full collections, allocation stalls or failures, and out-of-memory events.
Include allocation spikes and other stressful but representative periods: an average load can hide the headroom problem that appears only during bursts. Do not call a benchmark result universal unless its workload and environment are disclosed and reproducible.
Best Value
What to investigate when G1 misses its target
Use the logs to identify a cause before changing flags. Oracle’s G1 tuning guide points to areas including humongous allocations, marking that starts too late, remembered-set work, and concurrent refinement when logs indicate those symptoms.
- Inspect GC logs to identify which pause phase or collection behavior coincides with the latency problem.
- Check whether the logs show humongous allocations, marking pressure, remembered-set work, concurrent refinement, or evacuation trouble.
- Change one relevant variable—such as heap sizing or the pause-time goal—at a time, then repeat the same representative workload and compare latency, throughput, CPU, and headroom.
Changing the goal or heap size can shift the balance between latency and throughput; neither is a generic fix to apply without evidence.
Verify collector and mode support before deployment
Collector behavior and command-line flags vary by JDK release and vendor distribution. Before using a non-default collector or a specific mode, check the documentation for the exact runtime build, confirm that it accepts the relevant options, and validate the change under production-like conditions. This is especially important for Shenandoah, whose availability and supported modes are distribution-dependent.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




