Minecraft Java Performance

Java Versions for Minecraft Server Hosting: 8, 17, 21, and Why It Matters

By Witchly Team · · 9 min read

If you’ve ever tried to launch a Minecraft server and seen UnsupportedClassVersionError or Server requires Java X in the console, the issue is almost always a Java version mismatch. Minecraft’s Java requirements have changed a lot over the years, and using the wrong version is one of the most common causes of “my server won’t start.”

This post explains which Minecraft version needs which Java, why those requirements exist, what tradeoffs come with each Java version, and how Witchly automatically picks the right one when you deploy.

The short version

Minecraft versionRequired Java
1.8 – 1.16.5Java 8
1.17 (only)Java 16
1.18 – 1.20.4Java 17
1.20.5 and newerJava 21

Run too old a Java version → server refuses to start with UnsupportedClassVersionError. Run too new a Java version → usually works for newer MC, but older MC versions and some plugins/mods may break with reflection or library issues.

Match Java to your Minecraft version. Everything else flows from that.

Why Java versions matter at all

Minecraft is written in Java, which means the server runs inside a Java Virtual Machine (JVM). The JVM is responsible for executing the bytecode the game produces, managing memory, and handing your code to the CPU.

Different Java versions are different JVMs. They support different language features (e.g., Java 17 has features Java 8 doesn’t), include different garbage collectors, and produce slightly different runtime behaviour. When Mojang built a new Minecraft version against Java 17, they used Java-17-only features in the bytecode. A Java 8 JVM literally can’t read those instructions — hence the version error.

Going the other way (running old code on a newer Java) is usually fine — newer JVMs are mostly backward-compatible — but “usually” is doing a lot of work in that sentence. Reflective code (used heavily by plugins like ProtocolLib, ViaVersion, NoCheatPlus) sometimes breaks because Java 17+ restricted access to internal classes that older code relied on. That’s why some plugins still need Java 8 even though MC has moved on.

Java 8: the old-school workhorse

Java 8 was Minecraft’s required runtime from MC 1.8 (2014) through 1.16.5 (2021). It’s still actively maintained by various distributions (OpenJDK, Adoptium Temurin, Amazon Corretto) and is the right choice for:

  • Servers running 1.8–1.16.5
  • Modpacks built on those older MC versions (which is most of them — RLCraft, FTB legacy packs, SkyFactory 4, etc.)
  • Anything where ancient plugins must work and you can’t update them

Java 8’s garbage collectors (CMS, G1) were good for their era but lag behind newer collectors. You’ll see slightly higher tick lag during garbage collection events compared to Java 17/21, especially on RAM-heavy servers. For most purposes that doesn’t matter; for performance-sensitive setups it adds up.

Java 16: the one-version curiosity

MC 1.17 (June 2021) was the only Minecraft version that required Java 16 specifically. Mojang then moved to Java 17 for 1.18.

If you’re hosting a 1.17 server, you need Java 16. If you’re not, you can mostly forget Java 16 exists. The version is no longer actively supported by most distributions.

Java 17: the modern default

Java 17 became Minecraft’s required runtime starting with 1.18 (December 2021). It’s a Long-Term Support (LTS) release, which means major distributions will keep updating it for years.

Use Java 17 for:

  • MC 1.18 through 1.20.4
  • Most modpacks released between late 2021 and early 2024 (anything using NeoForge for 1.19/1.20 or Fabric for similar versions)

Java 17’s garbage collector lineup is significantly better than Java 8’s. The default G1GC is well-tuned for Minecraft’s allocation patterns, and ZGC (an experimental ultra-low-pause collector) is available if you want to tinker.

You don’t get Java 8’s plugin compatibility issues with Java 17 — most modern plugins target Java 17 or are compatible with it.

Java 21: the current latest

Java 21 (LTS, released September 2023) is required for MC 1.20.5 (April 2024) and everything newer (1.20.6, 1.21, etc.).

Java 21 introduced virtual threads, which under the hood let the JVM handle massive concurrency far more efficiently. Mojang has been incrementally adopting these features in newer MC versions, which is part of why MC 1.20.5+ requires Java 21 — they’ve started using language features that don’t exist in older JVMs.

For modern Minecraft (1.20.5+, 1.21+), Java 21 is the only choice. You can’t legally run a 1.21 server on Java 17 — the bytecode genuinely won’t execute.

How Witchly handles all this

Witchly’s deploy wizard handles Java-version matching automatically.

When you start a Minecraft deployment:

  1. Pick the Minecraft version you want (the wizard fetches the live list from Mojang’s version manifest, so the latest version appears within minutes of release)
  2. Witchly’s smart picker auto-selects the matching Java version based on the version you chose
  3. Your server deploys with the correct Java image baked in

You don’t manually pick Java 8 vs 17 vs 21. The platform reads the version table above and picks for you.

What if I change my mind?

Your server’s Java version is set by its Docker image — visible and editable on the Startup tab in your dashboard. If you ever want to switch:

  • Upgrading your MC version (1.20.4 → 1.21)? Update both the version (in your startup script or config) and the Docker image (in the Startup tab) to a Java 21 image. Witchly’s Startup tab shows the available images.
  • Downgrading your MC version (1.21 → 1.18)? Update both — drop your Java image down to Java 17 to avoid plugin compat issues.
  • Mismatch you didn’t realise? When the dashboard detects your selected Java image doesn’t match what your MC version expects, you’ll see a Java mismatch banner on the Startup tab with a one-click fix. Use it.

The banner exists specifically because manual edits drift over time, and a mismatched Java is the most common server-start failure. Save yourself the headache and let the banner fix it.

Plugin and mod compatibility notes

A few plugin/mod ecosystem realities:

Old plugins on new Java

Plugins compiled for Java 8 generally run fine on Java 17 — but plugins that use deep reflection (accessing private fields and methods of internal Bukkit/Spigot classes) sometimes break. ProtocolLib, ViaVersion, and various optimisation plugins fall in this bucket.

If a plugin breaks after a Java upgrade, check the plugin’s GitHub or its developer’s discord — almost every active plugin has been updated for newer Java versions, but you may need to download a newer build.

Fabric/Forge mods

The mod ecosystem is generally faster to adopt new Java versions than the plugin ecosystem (because mods are often distributed bundled with the loader rather than as binary jars meant to plug into a running JVM). Modpacks for 1.20+ all expect Java 17 or 21. Modpacks for 1.16 expect Java 8.

Mixed-version multi-bot setups

If you’re running, say, a 1.16.5 modded server alongside a 1.21 vanilla server, you need two separate Witchly servers (each on its own Java image). Don’t try to share one server between MC versions — Java version mismatches are unsolvable that way.

Performance differences in practice

Honest take: for a small-to-mid server (under 30 concurrent players), the Java version’s performance difference is hard to feel. The garbage collector improvements between Java 8 and Java 21 are real but show up mostly under heavy memory pressure — large modpacks with 50+ players, or complex automation farms running thousands of operations per tick.

For those workloads:

  • Java 21 G1GC is substantially better than Java 8’s GC. Tick stutters from GC are much shorter.
  • Java 21’s ZGC is even better but requires careful tuning. Experimental for most server admins; only worth trying if you’ve measured GC stutters as a problem.
  • JVM flags from “Aikar’s Flags” (a well-known set of Minecraft-specific GC tunings) work on Java 17 and 21 with minor tweaks. For Java 8, the original Aikar flags still apply.

The dashboard’s resource graphs show real-time RAM and CPU usage — if you see RAM saturating during peak play, that’s a hint to either upgrade your plan or look at GC tuning. Don’t tune flags blindly; measure first.

Common Java-version pitfalls

”It worked on my local PC but not on the server”

Your local installation has whatever Java version your Minecraft launcher includes (which auto-matches). The server doesn’t. Check the server’s Java image matches the MC version.

”Switched to Java 21 and a critical plugin stopped working”

That plugin uses internal class access that Java 17+ restricts. Either update to a newer plugin build, contact the plugin author, or roll back the Java image.

”I want the latest Java for performance — does that mean Java 21 always?”

For MC 1.20.5+, yes. For older MC versions, no — Java 21 may not improve much, and you risk plugin incompatibility. Match Java to MC version first; tune GC flags second.

”My modpack ships its own Java installation”

Some modpack launchers bundle Java. On a server, the Java image you set is the only one that matters; the modpack files don’t include a JVM.

”Too many open files” or weird memory errors after upgrading

Java 17+ has different defaults for some JVM settings. If you used custom flags on Java 8, recheck them — some flags were removed in newer Javas. Aikar’s Flags has up-to-date versions for each major Java release.

Summary

The whole topic boils down to: pick the right Java for your MC version, let the dashboard’s auto-detection handle it, and only manually intervene when the Java mismatch banner tells you something is off.

For a deeper reference on the Witchly deploy flow, see the Minecraft getting-started doc and the version-switching doc.