Which Java version do I need? An overview for servers

Published on 15 min read

Which Java version your application really needs, which one your distribution actually offers, and how to run several versions in parallel and switch between them cleanly.

Java is rarely an end in itself on a server. It is there because a Minecraft server, a Tomcat, a Jenkins or a search index demands it. That is exactly why the question is never "which Java is the best one", but "which Java does this particular application expect, and can I even get it on this particular operating system". This article answers both: with support timelines, with an availability table that we measured in real containers, and with the practical side of running several versions in parallel.

The short version: which release for which purpose

If you are short on time, this is the decision:

  • New project, free choice: Java 21. It is currently the most broadly supported LTS line, packaged and ready to use in Debian 13 and in every current Ubuntu release, and practically every current piece of server software runs on it.
  • Minecraft 1.20.5 to 1.21.11: Java 21. Mandatory, no leeway.
  • Minecraft 26.1 and newer: Java 25.
  • Older application whose documentation says "Java 17": take Java 17, not "17 or newer". With modloaders and plugin systems, "newer" is often not true.
  • Java 8 or 11: only when a legacy application forces it. Both belong on your list of things that have to be replaced.
  • Java 25: the newest LTS line, a sensible choice for new deployments, but check first whether your framework is already officially cleared for it.

For the installation itself we have separate guides: Installing Java 17 on Debian and Installing Java 21 on Debian. This article is the map above them.

What LTS means and how long the versions are maintained

A new Java major release appears every six months. The vast majority of them are dead after exactly six months: Java 22, 23, 24 and 26 stop getting security updates the moment the next release arrives. You do not want those on a server.

Only the LTS versions (Long Term Support) are interesting. They have appeared every two years since 2021: 8, 11, 17, 21, 25, and Java 29 is planned next for September 2027. Only these lines receive quarterly security updates over a span of years.

The distinction between Oracle and the free builds matters. For server use you will normally reach for OpenJDK from the distribution package or for Eclipse Temurin. Both are free to use, and in some cases maintenance there runs considerably longer than under Oracle's free license.

VersionReleasedStatusTemurin builds at least until
Java 82014LTS, legacyDecember 2030
Java 112018LTS, winding downOctober 2027
Java 172021LTS, widely usedOctober 2027
Java 212023LTS, default choiceDecember 2029
Java 252025LTS, currentSeptember 2031

The row for Java 17 surprises a lot of people: only until October 2027. Java 17 feels new, but it is already the second to last LTS generation. If you are setting up a system today that is meant to run for three years, plan with 21 or 25 from the start.

Which Java version your distribution has in its own repository

This is where most guides on the internet fall apart: they write "apt install openjdk-17-jre-headless" and assume that this works everywhere. It does not. We measured the package situation on 27 July 2026 in fresh containers.

PackageDebian 13Debian 12Ubuntu 24.04Ubuntu 22.04
openjdk-8-jre-headlessmissingmissing8u4928u492
openjdk-11-jre-headlessmissingmissing11.0.3111.0.31
openjdk-17-jre-headlessmissing17.0.1917.0.1917.0.19
openjdk-21-jre-headless21.0.11missing21.0.1121.0.11
openjdk-25-jre-headless25.0.3missing25.0.325.0.3

Read the Debian columns twice. Debian 12 knows Java 17 and nothing else. Debian 13 no longer knows Java 17, but does have 21 and 25. So there is not a single version in the official Debian sources that exists on both releases. Anyone writing a deployment script that has to run on bookworm and trixie cannot rely on one package name.

Ubuntu is more pleasant in this respect: all five LTS lines sit next to each other in the repository, on 22.04 just as on 24.04. If you need a system where a legacy application on Java 8 and a modern service on Java 21 run at the same time, Ubuntu is the shortcut.

When in doubt, check for yourself instead of guessing:

apt update
apt-cache policy openjdk-21-jre-headless
apt-cache search openjdk-

If "Candidate" shows (none), the package does not exist on this distribution. On the Red Hat family (AlmaLinux, Rocky, RHEL, Oracle Linux) the packages carry different names, and you list them like this:

dnf list java-\*-openjdk-headless
dnf install -y java-21-openjdk-headless

For the overview use dnf list and not dnf list available. The latter hides packages that are already installed, so after installing Java 21 it no longer shows up in the list at all and you end up looking in the wrong place. The situation in the Red Hat family, likewise measured in fresh containers:

PackageAlmaLinux 10AlmaLinux 9, Rocky 9, Oracle 9
java-1.8.0-openjdk-headlessmissingavailable
java-11-openjdk-headlessmissingavailable
java-17-openjdk-headlessmissingavailable
java-21-openjdk-headless21.0.1221.0.11 to 21.0.12
java-25-openjdk-headlessavailableavailable

AlmaLinux 10 has therefore made the same cut as Debian 13 and dropped everything below 21. A dnf install java-17-openjdk-headless ends there with No match for argument.

headless or not, JRE or JDK

On a server, always take the -headless variant. It leaves out the graphical libraries and therefore pulls in no X11 dependencies, which saves dozens of pointless packages on a root server. And -jre-headless is enough as long as you only run finished JAR files. Only once you compile yourself, or a tool calls javac, do you need openjdk-21-jdk-headless.

On the Red Hat family it is worth a second look at the dependencies at this point. On AlmaLinux 9, the package java-21-openjdk-devel pulls in a surprisingly long chain of graphical packages, among them webkit2gtk3-jsc, xorg-x11-fonts, xdg-desktop-portal and wireplumber. On a server without a desktop you do not want any of that. So check in advance with dnf install --assumeno what actually comes along, and stay with java-21-openjdk-headless as long as you do not have to compile anything.

Minecraft: game version to Java version

Minecraft is the most common reason anyone puts Java on a server in the first place, and at the same time the area with the strictest requirements. The mapping is unambiguous:

Minecraft Java EditionJava required
1.6.1 to 1.11.2Java 6 or newer
1.12 to 1.16.5Java 8 or newer
1.17 to 1.17.1Java 16 or newer
1.18 to 1.20.4Java 17 or newer
1.20.5 to 1.21.11Java 21 or newer
26.1 and newerJava 25 or newer

Two things about this that most tables leave out. First: with 26.1, Minecraft abandoned the old 1.x scheme and moved to a year-based scheme, so 26.1 is the first release of the year 2026. 1.21.11 was the last version that gets by with Java 21.

Second: the "or newer" applies to the vanilla server. As soon as modloaders are involved, it no longer holds reliably. A Forge server for 1.20.1 is built on Java 17, and putting it on Java 21 is one of the most common causes of crashes right at startup, even though the number is "bigger". For modded servers, take exactly the version that the modpack author names.

The practical steps are covered in our guides Installing a Minecraft server on Debian and Starting a Minecraft server automatically.

Other server applications and what they require

Beyond Minecraft, these rules apply as a rough guide:

  • Apache Tomcat: 9.0.x runs from Java 8 upwards, 10.1.x requires at least Java 11, 11.0.x requires at least Java 17. All three currently maintained branches run cleanly on Java 17.
  • Elasticsearch and OpenSearch: they bring their own JVM. Do not install a system Java for them and do not set a global JAVA_HOME that overrides the bundled JVM. That is a classic source of errors after a "cleanup" of the Java installation.
  • Jenkins: current versions require at least Java 17 and run on Java 21.
  • Keycloak, Kafka, Solr, Nexus: they follow the second to last LTS. Check the release notes of the specific version, these projects raise the minimum regularly.

Not every piece of server software that people associate with Java actually needs it. The TeamSpeak 3 server, for example, is a native binary and works without a JVM.

Running several Java versions in parallel and switching between them

On Debian and Ubuntu you can install as many OpenJDK packages at the same time as you like. Each one lands in its own directory under /usr/lib/jvm/ and they do not get in each other's way:

apt install -y openjdk-21-jre-headless openjdk-25-jre-headless
ls /usr/lib/jvm/

What they do share is exactly one file: /usr/bin/java. It is a symlink managed by the alternatives system. You can list the candidates like this:

update-alternatives --list java
update-alternatives --display java

This spelling, with the name after --list, is specific to Debian; on the Red Hat family it looks different, more on that below. The output of --display is the more useful of the two. It shows not only the paths, but also the mode (auto or manual) and the priority of every entry. Switching works interactively with update-alternatives --config java and a numeric selection, in scripts you are better off pinning it:

update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java
java -version

Never copy the path from someone else's tutorial, take it from update-alternatives --list java. The path shown above applies to OpenJDK from the distribution package. Anyone following the Temurin section further down does not have that directory at all: there it is called /usr/lib/jvm/temurin-21-jre-amd64/bin/java, and the command aborts with alternative path ... doesn't exist.

If you also compile, javac has to be switched separately. That is easily forgotten and leads to the absurd situation of compiling with Java 25 and starting with Java 21:

update-alternatives --set javac /usr/lib/jvm/java-21-openjdk-amd64/bin/javac
javac -version

The trap that costs you a night

As long as java is in auto mode, the highest priority always wins, and the highest priority belongs to the newest installed version. So if you add openjdk-25 months later because another service needs it, /usr/bin/java silently jumps to 25 during the next package operation. Your Minecraft server, which had been running on 21 until then, starts on a JVM you never selected after the next reboot.

update-alternatives --set switches the entry to manual and freezes it there. That is the real purpose of the command. You get back into automatic mode with:

update-alternatives --auto java

The more robust route for services is still not to rely on /usr/bin/java at all. Put the full path into your systemd unit, then the version choice is fixed per service and independent of any alternatives switch:

ExecStart=/usr/lib/jvm/java-21-openjdk-amd64/bin/java -Xms2G -Xmx4G -jar server.jar nogui

What such a unit looks like in full is described in Creating a systemd service. Incidentally, that same absolute path is also the reason why a service sometimes does not move along after a Java switch: update-alternatives simply does not touch it.

On AlmaLinux, Rocky Linux, RHEL and Oracle Linux the tool is called alternatives, and update-alternatives is only a symlink to it there. It does not work identically, though: this --list takes no argument. A copied update-alternatives --list java only prints the help text there and exits with return code 2. One of these two lines is correct:

alternatives --list | grep java
alternatives --display java

The output of --display differs as well: instead of java - auto mode it reads java - status is auto. On the Red Hat family the paths also carry the full version number, for example /usr/lib/jvm/java-21-openjdk-21.0.11.0.10-1.el9.x86_64, and not the short Debian form java-21-openjdk-amd64. Only AlmaLinux 10 additionally creates a short symlink java-21-openjdk.

And the automatic mode behaves differently there from what you would expect: after installing Java 17 next to an already present Java 21, alternatives on AlmaLinux 9 switched the link /usr/bin/java to 17 on its own, so to the older version. For that reason, set alternatives --set java <path> explicitly after every additional installation and verify with java -version.

When the distribution does not have the version: Temurin

There is a clean answer for the gaps in the table above: Eclipse Temurin from Adoptium supplies temurin-8 through temurin-26 for trixie, bookworm, noble and jammy. That gets you Java 21 on Debian 12 as well, and Java 17 on Debian 13, without third-party PPAs or hand-copied tarballs in /opt.

Note that apt-key is deprecated. The key belongs in /etc/apt/keyrings/ and is referenced via signed-by:

apt install -y wget gnupg ca-certificates apt-transport-https
install -d -m 0755 /etc/apt/keyrings
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public | gpg --dearmor | tee /etc/apt/keyrings/adoptium.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/adoptium.gpg] https://packages.adoptium.net/artifactory/deb $(awk -F= '/^VERSION_CODENAME/{print$2}' /etc/os-release) main" | tee /etc/apt/sources.list.d/adoptium.list
apt update
apt install -y temurin-21-jre

Temurin packages register themselves in the alternatives system as well, so they show up in update-alternatives --display java and can be mixed with the distribution's own OpenJDK packages. Their directories live under /usr/lib/jvm/temurin-21-jre-amd64 or under a similarly named path.

Error messages verbatim and what they mean

E: Unable to locate package openjdk-17-jre-headless
That version does not exist in this distribution. On Debian 13 this is the normal case for Java 8, 11 and 17. No typo, no missing apt update: use Temurin or a different version.

java.lang.UnsupportedClassVersionError: ... has been compiled by a more recent version of the Java Runtime (class file version 65.0), this version of the Java Runtime only recognizes class file versions up to 61.0
The classic. The application was built for a newer JVM than the one you started. The numbers translate like this:

class file versionJava
52.08
55.011
60.016
61.017
65.021
69.025

So 65.0 against 61.0 means, in plain terms: the software wants Java 21, you are running Java 17. On Minecraft servers from 1.20.5 onwards you often see this error wrapped as Error: LinkageError occurred while loading main class net.minecraft.bundler.Main, with the actual cause on the line below it.

java: command not found
Either no JVM is installed, or you have only unpacked a JDK directory into /opt without registering it. Check ls /usr/lib/jvm/. If there are directories there but /usr/bin/java is missing, register the entry afterwards:

update-alternatives --install /usr/bin/java java /usr/lib/jvm/java-21-openjdk-amd64/bin/java 2111

update-alternatives: error: no alternatives for java
The alternatives system does not know a single candidate. This happens when Java was installed by hand. Same fix as above.

update-alternatives: error: alternative path /usr/lib/jvm/... doesn't exist
You have set a path that has since disappeared, typically after an uninstall. Make sure Debian paths contain the architecture: java-21-openjdk-amd64, not java-21-openjdk.

The service runs, but on the wrong version.
Very likely the systemd unit contains an absolute path, or the unit sets its own JAVA_HOME. Both override update-alternatives without any warning.

The server starts but dies after a few seconds with no comprehensible message.
With Java applications this is often not a version problem but a shortage of memory: the kernel kills the process when -Xmx is set larger than the free RAM. Our articles Setting up swap against out of memory and Disk full on Linux: how to clean up fit here.

How to tell that the right version is really running

The first check is trivial, but do it after every switch anyway:

java -version

The output has to name the expected major version, for example openjdk version "21.0.11". The second check is the more informative one, because it shows the path that is actually resolved and therefore also whether you have just caught Temurin or the distribution's OpenJDK:

readlink -f "$(command -v java)"

Use command -v here deliberately and not which. which is an external program, and in the minimal installation of AlmaLinux 9 and 10, Rocky Linux 9 and Oracle Linux 9 it is not included at all. The variant with which ends there with which: command not found, followed by readlink: missing operand. command -v is a shell builtin and works on all of the distributions named.

And if you want to know what the JVM itself thinks about its home, because an application evaluates JAVA_HOME:

java -XshowSettings:properties -version

In the output, java.home and java.version are the interesting lines. If java.home deviates from what you expect, a JAVA_HOME is set somewhere and it wins.

For a running service, in the end only what the process itself uses counts. You can read that straight out of the process list, which shows the full path of the JVM it was started with:

ps -eo pid,args | grep '[j]ava'

If you see /usr/lib/jvm/java-21-openjdk-amd64/bin/java there, the matter is settled. If you see a bare java, your service hangs on the alternatives symlink and moves with it. For a production service that is the worse of the two variants.

If you are setting up a server from scratch anyway, it is worth reading our checklist for new root servers first: Java belongs at the end of that list, not at the beginning, because troubleshooting a JVM only becomes enjoyable once SSH access, firewall and time zone are working.

In summary

Java 21 is the standard answer today, Java 25 the future-proof one, Java 17 the one winding down, and Java 8 and 11 are migration debt. What decides the matter is not the number alone, but the combination of application and distribution: Debian 12 gives you only 17, Debian 13 only 21 and 25, Ubuntu gives you everything. Where the package is missing, Temurin fills the gap. And as soon as more than one version sits on the machine, the rule is: update-alternatives --set instead of automatic mode, and in systemd units better the absolute path right away.

Frequently asked questions

Which Java version should I install on a new server in 2026?
Java 21 if you have a free choice. It is the most broadly supported LTS line, sits ready to use in the repository of Debian 13 as well as Ubuntu 22.04 and 24.04, and Adoptium promises builds at least until December 2029. Java 25 is the newer LTS line and makes sense when your application is officially cleared for it.
Why can I not find openjdk-17-jre-headless on Debian 13?
Because the package does not exist there. Debian 13 ships only openjdk-21 and openjdk-25, while Debian 12 ships only openjdk-17. The message E: Unable to locate package openjdk-17-jre-headless is therefore correct and not a mistake on your side. In that case use the Temurin packages from Adoptium, which offer temurin-8 through temurin-26 for trixie and bookworm.
Which Java version does my Minecraft server need?
1.12 to 1.16.5 need Java 8, 1.17 and 1.17.1 need Java 16, 1.18 to 1.20.4 need Java 17, 1.20.5 to 1.21.11 need Java 21, and 26.1 and newer need Java 25. The respective or newer applies to the vanilla server; with Forge, NeoForge and modpacks take exactly the version the author names.
Can I install several Java versions at the same time?
Yes. The OpenJDK packages each live in their own directory under /usr/lib/jvm/ and do not interfere with each other. The only shared item is the symlink /usr/bin/java, which you pin with update-alternatives --set java /usr/lib/jvm/java-21-openjdk-amd64/bin/java. Do not forget javac, that one is switched separately.
What does UnsupportedClassVersionError with class file version 65.0 mean?
The application was built with a newer JVM than the one you are starting. 52.0 corresponds to Java 8, 55.0 to Java 11, 61.0 to Java 17, 65.0 to Java 21 and 69.0 to Java 25. If the message says 65.0 against 61.0, the software wants Java 21 but is currently running on Java 17.
Why does my service still use the old Java version after switching?
Because update-alternatives only redirects /usr/bin/java. If your systemd unit contains an absolute path such as /usr/lib/jvm/java-17-openjdk-amd64/bin/java or its own JAVA_HOME, that wins. Check with ps -eo pid,args | grep '[j]ava' which binary the running process actually uses.
How long will Java 17 be maintained?
Eclipse Temurin commits to builds for Java 17 at least until October 2027, exactly as long as for Java 11. Java 17 feels new, but it is already the second to last LTS generation. For systems that are meant to run for several years, plan with Java 21 or 25 from the start.

Java OpenJDK LTS Minecraft Debian Ubuntu update-alternatives Temurin Server maintenance