-XX:+UseG1GCEssentialEnables the G1 garbage collector. G1 trades raw throughput for short, predictable pause times — crucial because Minecraft's main thread can't tolerate a 500ms GC pause without players noticing.
The JVM tuning that's been the de-facto Minecraft server standard for nearly a decade — broken down flag by flag. What each does, why it matters, and which still belong in 2026 on Java 21.
java -Xms6G -Xmx6G \ -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 \ -Dusing.aikars.flags=https://mcflags.emc.gs \ -Daikars.new.flags=true \ -jar paper.jar nogui
Replace 6G with your actual RAM (matched -Xms and -Xmx — see flag details below). On panel hosts including CoalHost, these are applied automatically.
Minecraft's server runs on a single-threaded tick loop with a 50ms budget. Garbage collection — the JVM reclaiming dead objects — happens on the same thread, so a long GC pause directly causes a TPS drop. The default JDK garbage collector is tuned for throughput-oriented enterprise apps; it happily takes 800ms pauses. Aikar Cooke (formerly EMC, now a Paper maintainer) tuned G1GC specifically for Minecraft's allocation pattern: lots of short-lived objects, bursty allocations during chunk loads, and a hard pause-time ceiling.
-XX:+UseG1GCEssentialEnables the G1 garbage collector. G1 trades raw throughput for short, predictable pause times — crucial because Minecraft's main thread can't tolerate a 500ms GC pause without players noticing.
-XX:+ParallelRefProcEnabledEssentialProcesses weak/soft/phantom references in parallel during GC. Minecraft creates lots of these (entity refs, chunk refs), and serial processing turned into a bottleneck on bigger servers.
-XX:MaxGCPauseMillis=200EssentialTells G1 to aim for ≤200ms pauses. G1 then sizes its young-generation regions to hit that target. Lower = more frequent but shorter pauses, higher = rarer but longer.
-XX:+UnlockExperimentalVMOptionsEssentialEnables the JVM flags marked 'experimental' (like the G1NewSize percentages below). Required for the rest of Aikar's tuning to apply.
-XX:+DisableExplicitGCEssentialIgnores any plugin or mod that calls `System.gc()` manually. Some old plugins do this thinking it helps; in reality, it forces a full stop-the-world collection that freezes the server for a second.
-XX:+AlwaysPreTouchImportantTouches every page of the heap at startup, forcing the OS to actually allocate the memory rather than lazy-allocating it on first use. Adds ~30s to startup but eliminates random TPS dips later when new heap pages are committed.
-XX:G1NewSizePercent=30ImportantReserves 30% of the heap for the young generation (vs JDK default of ~5%). Minecraft creates massive amounts of short-lived objects (chunk packets, entity ticks), so a big young gen avoids promoting garbage into old gen.
-XX:G1MaxNewSizePercent=40ImportantCaps young gen growth at 40%. Without this, G1 will sometimes grow young gen to 80%+ and starve old gen, triggering full GCs.
-XX:G1HeapRegionSize=8MImportantSets G1's region size to 8MB. Default is auto-calculated and often picks 4MB on a 6GB heap — too small for the chunk-sized allocations Minecraft does (causes 'humongous allocation' overhead).
-XX:G1ReservePercent=20TuningReserves 20% of heap to absorb GC promotion failures. Higher than JDK default (10%) because Minecraft's allocation pattern is bursty — chunk loads can promote a lot at once.
-XX:G1HeapWastePercent=5TuningTriggers GC when 5% of the heap is unreclaimed garbage (default 10%). More aggressive collection = more CPU, but smaller working set and less chance of full GC.
-XX:G1MixedGCCountTarget=4TuningSpreads mixed-mode collection across 4 GC cycles. More cycles = each one is faster, less impact per pause.
-XX:InitiatingHeapOccupancyPercent=15TuningStarts a concurrent GC marking cycle when the heap is 15% full (default 45%). Aggressive, but matches Minecraft's allocation rate. Hits old gen before it fills, avoiding emergency full GCs.
-XX:G1MixedGCLiveThresholdPercent=90TuningMixed GC will reclaim regions that are up to 90% live (default 65%). Minecraft has lots of long-lived data (loaded chunks, world state); a higher threshold prevents G1 from skipping over them.
-XX:G1RSetUpdatingPauseTimePercent=5TuningLimits remembered-set update work to 5% of pause time. Keeps GC pauses short by deferring some bookkeeping to concurrent threads.
-XX:SurvivorRatio=32TuningSurvivor spaces are 1/32 of young gen (vs default 1/8). Minecraft's allocation pattern means most objects either die immediately or live forever — minimal survivor space avoids wasted copying.
-XX:+PerfDisableSharedMemTuningDisables the JVM's shared performance counters file. Tools like jstat won't work, but the file's I/O has been linked to GC pauses on busy systems.
-XX:MaxTenuringThreshold=1TuningPromotes survivors to old gen after 1 GC cycle (default 15). Combined with the small survivor space — anything that survives once is going to live forever, so don't waste cycles copying it.
Java 21 is now the baseline for Minecraft 1.20.5+. The good news: every Aikar flag still applies — G1GC has been continuously improved between Java 8 and 21 but the API surface hasn't changed. The full flag set works as-is.
Generational ZGC (Java 21+, -XX:+UseZGC) is the most exciting alternative. Its sub-millisecond pause times sound perfect for Minecraft, but it has higher per-allocation overhead. In our benchmarks it loses to Aikar-G1 on heaps under 16 GB by 5-10% TPS. ZGC becomes worth considering above 32 GB, where G1's young-gen sizing starts struggling.
What to skip: CMS (deprecated since Java 14, removed in 15), Shenandoah (similar tradeoff to ZGC, no clear win for MC), Parallel GC (high throughput but unbounded pauses).
Yes — the core G1GC tuning is still the right default for Minecraft on Java 21, and Paper, Purpur and most modpack launchers still ship them as the default. They were tuned for Minecraft's specific allocation pattern, which hasn't fundamentally changed.
ZGC has very low pause times (sub-millisecond) but trades that for higher allocation overhead. On heaps under 16 GB, Aikar-tuned G1GC usually wins on TPS. ZGC starts to shine on 32+ GB heaps where G1's young-gen sizing struggles. For typical Minecraft servers, stick with G1GC and Aikar's flags.
Yes — they're loader-agnostic. The flags configure the JVM, not Minecraft. They work for vanilla, Paper, Forge, Fabric and NeoForge equally. Modpack launchers like CurseForge and Modrinth ship them by default.
If you only set a few, the must-haves are: -XX:+UseG1GC (the collector), -XX:MaxGCPauseMillis=200 (the pause target), -XX:G1NewSizePercent=30 and -XX:G1MaxNewSizePercent=40 (the young-gen sizing). The tuning-level flags individually have small effects but compound — use the full set.
Setting them equal (e.g., both 6G) makes the JVM allocate the full heap upfront instead of growing it on demand. Combined with -XX:+AlwaysPreTouch, this avoids mid-game pauses when the heap expands and the OS has to commit pages.
Pick the right amount for your use case (4-6 GB vanilla, 6-8 GB light modded, 10-12 GB heavy modpacks) — Aikar's flags don't change that. They make the RAM you have work better; they don't substitute for having enough.
Every Minecraft server on CoalHost starts with Aikar's flags pre-configured for your RAM size. No manual tuning needed.
View Minecraft Hosting →