
The Java garbage collector is the single most impactful JVM setting for Minecraft server performance. It determines when the server pauses to clean up unused memory, how long those pauses last, and how smoothly the tick loop runs. Most server operators copy JVM flags from a guide without understanding what they do. This post explains the two main options, when each one wins, and how to choose.
What the Garbage Collector Does
Java manages memory automatically. When your Minecraft server creates objects (entity data, chunk data, block states, player inventories), Java allocates memory for them. When those objects are no longer needed, the garbage collector reclaims that memory.
The problem is timing. When the GC runs, it can pause the server's main thread. In Minecraft, that main thread is the tick loop. A 50ms GC pause means the server misses a tick. Miss enough ticks and your TPS drops below 20, which players experience as rubber-banding, delayed block breaks, and laggy mob behavior.
Different garbage collectors have different strategies for minimizing these pauses.
G1GC: The Established Choice
G1GC (Garbage-First Garbage Collector) has been the default recommendation for Minecraft servers since around 2018. Aikar's famous flags use G1GC, and most hosting providers configure their servers with it.
How G1GC Works
G1GC divides the heap into regions and collects the regions with the most garbage first (hence "Garbage-First"). It does most of its work concurrently (in the background) but still needs short stop-the-world pauses for certain operations.
Aikar's G1GC Flags
The standard G1GC configuration for Minecraft:
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
These flags are well-tuned for Minecraft's allocation patterns. They keep GC pauses short (target 200ms max) and promote objects to the old generation quickly (MaxTenuringThreshold=1), which makes sense because Minecraft's long-lived objects (loaded chunks, entity registries) should not be repeatedly copied between survivor spaces.
G1GC Strengths
- Battle-tested with Minecraft for years
- Aikar's flags are optimized specifically for Minecraft's memory patterns
- Good throughput (total GC time as percentage of runtime)
- Works well from 4 GB to 16 GB heap sizes
- Compatible with Java 11, 17, and 21
G1GC Weaknesses
- Pause times increase with heap size. Above 12 GB, pauses can reach 100 to 200ms
- Not ideal for very large heaps (16+ GB) used by heavy modpacks
- Pause time is variable. Most pauses are short, but occasional long pauses happen
ZGC: The Low-Latency Alternative
ZGC (Z Garbage Collector) was designed for applications that need consistently low pause times, regardless of heap size. It achieves this by doing almost all GC work concurrently, keeping stop-the-world pauses under 1ms in most cases.
ZGC Flags for Minecraft
java -Xms10G -Xmx10G -XX:+UseZGC -XX:AllocatePrefetchStyle=1 -XX:-ZProactive -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+PerfDisableSharedMem -jar server.jar
ZGC needs fewer tuning flags than G1GC because it handles most optimizations internally. The -XX:-ZProactive flag disables proactive GC cycles that ZGC sometimes triggers unnecessarily for Minecraft's workload.
ZGC Strengths
- Sub-millisecond pause times regardless of heap size
- Scales to very large heaps (32 GB, 64 GB) without pause degradation
- More consistent performance: no random 200ms spikes
- The improved "Generational ZGC" in Java 21+ further reduces overhead
ZGC Weaknesses
- Higher total memory usage (ZGC needs more headroom, typically 15 to 20% more than G1GC for the same workload)
- Slightly lower throughput than G1GC (GC uses more total CPU time, but in smaller increments)
- Requires Java 17+ (Generational ZGC requires Java 21+)
- Fewer Minecraft-specific tuning guides available
- Some older plugins may not play well with ZGC's memory management
Benchmarks: What the Numbers Show
Testing on a Paper 1.21 server with 20 concurrent players, 50 plugins, view distance 10, on Ryzen 9 7950X with NVMe:
G1GC (Aikar's Flags, 10 GB Heap)
| Metric | Value |
|---|---|
| Average TPS | 19.8 |
| Worst 1% TPS | 18.2 |
| Average GC pause | 12ms |
| Max GC pause | 187ms |
| GC pauses over 50ms | 23 per hour |
| Total GC time | 2.1% of runtime |
| RSS memory | 11.2 GB |
ZGC (10 GB Heap)
| Metric | Value |
|---|---|
| Average TPS | 19.9 |
| Worst 1% TPS | 19.5 |
| Average GC pause | 0.4ms |
| Max GC pause | 2.1ms |
| GC pauses over 50ms | 0 per hour |
| Total GC time | 3.8% of runtime |
| RSS memory | 12.8 GB |
What This Means
Average TPS is nearly identical. The difference shows in consistency. G1GC's worst 1% TPS (18.2) includes moments where a long GC pause caused a tick to be delayed. ZGC's worst 1% (19.5) stays close to perfect because its pauses never exceed a few milliseconds.
The tradeoff: ZGC uses more total CPU time for garbage collection (3.8% vs 2.1%) and more memory (12.8 GB vs 11.2 GB). On a busy shared host where CPU and RAM are at a premium, G1GC is more efficient. On a server with headroom, ZGC's consistency advantage is significant.
Which One Should You Use
Use G1GC (Aikar's flags) if:
- Your heap is 4 to 12 GB
- You are on managed hosting where you pay per GB of RAM
- You are running Java 11 or 17
- The occasional 100ms+ pause is acceptable
- You want the most tested, most documented configuration
Use ZGC if:
- Your heap is 12 GB or larger (heavy modpacks)
- You are on Java 21+ (Generational ZGC is the best version)
- TPS consistency matters more than raw efficiency
- You have RAM headroom (budget 15 to 20% more than the G1GC requirement)
- You run a competitive or PvP server where micro-stutters affect gameplay
Use Generational ZGC (Java 21+) if:
- You want ZGC's pause characteristics with better throughput
- Your modpack targets Java 21 or newer
- You want the objectively best GC for large heaps in 2026
To enable Generational ZGC (the default ZGC mode in Java 21+):
java -Xms12G -Xmx12G -XX:+UseZGC -XX:+ZGenerational -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -jar server.jar
How to Switch
From G1GC to ZGC
- Replace your JVM flags. Remove all G1GC-specific flags (
-XX:G1*,-XX:MaxGCPauseMillis,-XX:SurvivorRatio, etc.) and add-XX:+UseZGC - Increase your Xmx by 15 to 20%. If you ran 10 GB with G1GC, set 12 GB for ZGC
- Make sure you are on Java 17+ (21+ for Generational ZGC)
- Restart and monitor TPS for the first hour
From ZGC to G1GC
- Replace
-XX:+UseZGCwith-XX:+UseG1GCand add Aikar's G1GC flags - You can reduce Xmx slightly since G1GC needs less headroom
- Restart and monitor
In both cases, the switch is just a flag change. No world data or configuration is affected. You can switch back and forth to test which one works better for your specific server.
Monitoring GC Performance
Use Spark (the Minecraft profiling plugin) to monitor GC behavior:
/spark gc
/spark gcmonitor
Spark shows GC pause frequency, duration, and type in real time. If you see pauses over 50ms regularly on G1GC, consider trying ZGC. If you see high total GC time on ZGC, consider switching to G1GC or increasing your heap.
Hosting Considerations
The GC choice interacts with your hosting plan. On Space-Node Minecraft hosting:
- Budget tier (Ryzen 9 3900X): G1GC with Aikar's flags is the best fit. The hardware is capable but not the fastest single-thread, so G1GC's lower CPU overhead is an advantage.
- Premium tier (Ryzen 9 9950X/7950X): either GC works well. ZGC's higher CPU usage is offset by the faster cores. If you are running a heavy modpack on 12+ GB, Generational ZGC on Java 21 is the strongest configuration.
Both tiers use NVMe storage, which matters because GC behavior can affect I/O patterns during chunk loading and saving.
FAQ
Can I use Shenandoah GC instead? Shenandoah is another low-pause collector, but it has less community testing with Minecraft than ZGC. It works, but ZGC (especially Generational ZGC on Java 21) has better performance characteristics for Minecraft's allocation patterns in 2026.
Do Aikar's flags work with ZGC? No. Aikar's flags are G1GC-specific. Many of the parameters (G1NewSizePercent, G1HeapRegionSize, etc.) are meaningless to ZGC and may cause errors. Use ZGC-specific flags when switching.
Should I use GraalVM with ZGC? GraalVM's JIT compiler and ZGC are independent features. You can run ZGC on GraalVM if you want both the JIT improvements and low GC pauses. Check our GraalVM Minecraft guide for setup details.
Related guides: for the full JVM flags reference, see Aikar's flags guide. For another performance angle, read GraalVM for Minecraft servers. Running a modpack? See ATM9 vs ATM10 comparison and best Minecraft mods 2026.
Does the GC choice affect chunk loading speed? Indirectly. G1GC's longer pauses can delay chunk loading during GC events. ZGC's sub-millisecond pauses mean chunk loading is more consistent. Players exploring new terrain will notice the difference.
What about client-side GC settings? The client benefits from ZGC too, especially with shaders and high render distances. But the server is where GC configuration matters most, because the server tick loop is the bottleneck for everyone's gameplay experience.