Ask ten Minecraft server owners what causes lag and most will blame plugins, players, or “the host.” In reality, a huge share of mysterious freezes, tick spikes, and “server not responding” complaints come from one place: the Java garbage collector. Every time the JVM pauses to clean up memory, your server stops ticking. Choose the wrong collector and those pauses can stretch into hundreds of milliseconds, exactly when your world is busiest.
This guide is written to help server owners, admins, and plugin developers settle the 2026 question of ZGC vs G1GC for Minecraft servers. It is built from the official JVM documentation, the well-known Aikar’s flags community standard, and hands-on testing on Java 21 and Java 24 with Paper 1.21. If you already run Minecraft server hosting and want to squeeze out the last few TPS, this is the missing piece.
Why the Garbage Collector Matters More Than You Think
Minecraft allocates memory constantly: chunks, entities, block updates, packets. The JVM occasionally stops all application threads to reclaim unused objects. That stop-the-world pause is invisible on a laptop but brutal on a server, because the main thread has a hard 50 millisecond budget per tick. Cross that line consistently and players see rubber-banding, hit-registration failures, and mob lag.
This is why [A Deep Dive into Aikar’s Flags: The Science of JVM Optimization] exists. Those flags tune one specific collector, G1GC, for Minecraft’s allocation pattern. But since Java 21 shipped generational ZGC, there is a serious alternative. Understanding both lets you choose deliberately instead of copying flags you found in a Discord message.
What Is G1GC?
G1 (Garbage First) has been the JVM default collector since Java 9. It divides the heap into regions and collects the ones with the most garbage first, aiming for a user-defined pause target (default 200 ms). It balances throughput and latency well for a general-purpose workload, which is why it has been the backbone of Minecraft optimization for years.
Reference: Oracle G1 Tuning Guide.
What Is ZGC?
ZGC is a low-latency collector designed to keep pauses under a millisecond, even on multi-terabyte heaps. It does almost all its work concurrently, while your threads keep running. The catch is higher CPU and memory overhead because of the concurrent barriers it relies on.
Generational ZGC (JEP 439) arrived in Java 21 and split the heap into young and old generations, fixing ZGC’s biggest weakness: it previously had to scan the entire heap for every collection cycle. Because most objects die young, generational ZGC does dramatically less work per cycle. Java 23 made generational ZGC the default (JEP 474), and Java 24 removed the non-generational mode entirely (JEP 490).
References: JEP 439: Generational ZGC | JEP 474 | Oracle ZGC Guide.
ZGC vs G1GC: Side-by-Side Comparison
| Metric | G1GC | ZGC (generational) |
|---|---|---|
| Typical pause time | 10-100 ms (target 200 ms) | Well under 1-5 ms |
| Throughput | High | Slightly lower (concurrent overhead) |
| CPU overhead | Low | Moderate to high |
| Heap headroom needed | Moderate | Higher |
| Best heap range | 2-16 GB | 16 GB and up |
| Default since | Java 9 | Generational: Java 23 |
| Minecraft requirement | Java 17+ | Java 21+ (1.20.5+) |
These are representative ranges from community and JVM benchmarking, not guarantees. Your plugin load, entity count, and CPU matter more than any single number. See the [Best CPUs for Minecraft Servers 2026] to understand how CPU headroom changes the math.
The Exact JVM Flags for Each Collector
Option A: G1GC (Aikar’s Flags)
java -Xms10G -Xmx10G -XX:+UseG1GC -XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions
-XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20
-XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4
-XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90
-XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32
-XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -jar server.jar nogui
Set -Xms and -Xmx equal to avoid heap resizing. Always leave 1-2 GB of system RAM free for the OS and off-heap work. Source: PaperMC Aikar’s Flags.
Option B: Generational ZGC
java -Xms24G -Xmx24G -XX:+UseZGC -XX:+ZGenerational
-XX:+AlwaysPreTouch -XX:+DisableExplicitGC -jar server.jar nogui
On Java 23 and later, drop -XX:+ZGenerational because it is the default, and on Java 24 the flag is gone because non-generational ZGC was removed. Keep the heap large enough that ZGC rarely needs to fall back to a stop-the-world cycle. Source: OpenJDK JEP 474.
So Which Should You Use in 2026?
- Use G1GC (Aikar’s flags) if you run 2-16 GB of heap on a typical VPS or dedicated box. It is battle-tested, light on CPU, and handles classic SMP loads beautifully.
- Use generational ZGC if you run 24 GB or more, host hundreds of players, run heavy modpacks, or see recurring pauses that survive G1 tuning and spark profiling.
- Measure before switching. A collector change without before-and-after data is just superstition.
For context on how the collector interacts with your CPU and RAM budget, see [CPU vs RAM: What Actually Stops Minecraft Lag in 2026?] and [Minecraft Server Hosting: Performance, RAM, and TPS Explained].
How to Benchmark a Garbage Collector Change Properly
- Record a baseline TPS and tick-duration graph with spark for at least 24 hours of normal play.
- Note peak MSPT (milliseconds per tick) and the frequency of spikes above 50 ms.
- Enable GC logging with
-Xlog:gc*:file=gc.log:time,uptimeto see pause lengths directly. - Change exactly one thing: the collector, not the heap size and collector at once.
- Run the same window again and compare pause distribution, not just averages.
Pros and Cons Summary
G1GC
- Pros: Default and well documented, low CPU cost, predictable performance on small and mid-size heaps, huge community knowledge base.
- Cons: Pauses can spike on large heaps or when the heap fills quickly; needs regular tuning as your server grows.
Generational ZGC
- Pros: Near-zero pause times, scales to very large heaps, ideal for big communities and heavy modpacks.
- Cons: More CPU and memory overhead, requires Java 21 or newer, less community tuning data for Minecraft specifically.
Common Mistakes to Avoid
- Setting
-Xmxhigher than-Xms. Heap resizing causes avoidable pauses. Make them equal. - Using non-generational ZGC on Java 24. It no longer exists. Let generational be the default.
- Leaving zero RAM for the OS. ZGC’s concurrency needs breathing room, not a fully committed machine.
- Mixing modded and vanilla assumptions. Heavy modpacks allocate far more, so they benefit from ZGC sooner.
- Blaming the collector for plugin lag. Profile first with spark; a bad plugin will lag on any collector.
Frequently Asked Questions
Is ZGC better than G1 for Minecraft?
It depends on heap size and CPU budget. ZGC gives far lower pause times but costs more CPU and memory. For small and mid-size servers G1GC with Aikar’s flags is usually the smarter choice.
Can I use ZGC on a 4 GB Minecraft server?
You can, but you generally should not. ZGC’s overhead is a poor trade at small heap sizes. Stick with G1GC until you are comfortably above 16 GB.
Which Java version do I need for generational ZGC?
Java 21 introduced generational ZGC, Java 23 made it the default, and Java 24 removed the old mode. Minecraft 1.20.5 and newer ship with Java 21, so most current servers qualify.
Do Aikar’s flags still work in 2026?
Yes. They remain the recommended G1GC configuration for most Minecraft servers and are maintained on the PaperMC documentation.
Conclusion: Tune for Your Server, Not for Twitter
G1GC is still the pragmatic default for most Minecraft servers in 2026, and generational ZGC is a genuine upgrade once your heap and player count grow large. The winning move is not picking a side, it is measuring. Record a baseline, change one variable, and let your own GC logs decide.
Your next step: run /spark profiler start, capture 24 hours of tick data, then compare your current collector against the alternative using the flags above. If you are still on an old JVM, upgrading Java is the single biggest TPS win available. Then read [Aikar’s Flags Explained: The Secret to Perfect Garbage Collection] to complete the picture.
Tuning ZGC for Minecraft: Heap and CPU Guidelines
Switching the collector is only half the job. ZGC needs a different mindset than G1. Because it does its work concurrently, it rewards generous heap headroom and punishes a machine that is already CPU-saturated. As a rule of thumb, give ZGC at least 25 percent more heap than you would give G1, and make sure the host still has 2 GB of RAM and a free CPU core for the operating system and off-heap work.
- Keep
-Xmsand-Xmxequal so the heap never resizes mid-session. - Leave at least one physical core with nothing else pinned to it; ZGC uses background threads.
- Do not over-allocate: an oversized heap with a weak CPU just moves the bottleneck.
- On modded servers, expect higher allocation rates and give ZGC even more headroom.
If your host is CPU constrained, G1GC will usually serve you better no matter how large the heap, because it spends fewer cycles on concurrent bookkeeping.
How to Read Your GC Logs
The GC log is the ground truth for any collector debate. Enable it, then look for pause length and frequency rather than raw totals.
- On G1, focus on events labeled
Pause YoungandPause Full; a growing count of long full pauses is your signal to switch. - On ZGC, watch for any stop-the-world cycle at all; the goal is to keep them rare.
- Correlate each long pause with a TPS dip in your spark timeline to confirm the collector is the cause.
Does ZGC use more RAM than G1?
Yes. ZGC trades memory and CPU for lower latency, so plan for a larger heap and more headroom on the host.
Will changing the collector fix laggy plugins?
No. A collector change only removes garbage-collection pauses. If spark shows a plugin hogging the main thread, fix the plugin first.

Leave a Reply