Use the latest Java Long-Term Support release

Java releases are made every six months in a 'feature-release-train' model, rather than having a major release planned for every two to four years as historically was the case. This rapid release cadence enables Oracle, and other participants in the Java ecosystem, to designate Long-Term Support (or LTS) releases every three years, with the most recent LTS releases being Java 11 (September 2018) and Java 17 (September 2021).

The major difference between non-LTS releases and LTS releases is that when a new release is made available (every six months), the previous non-LTS is out-of-support. When the release leaves support, it meanes that it won't receive quarterly security, stability, or performance updates any longer. Most organizations still prefer to target LTS versions for production use because it is not always possible to test and update their production JDK every six months.

Non‑LTS releases are considered a cumulative set of enhancements of the most recent LTS release. These are good releases to test with so that you can have higher degrees of confidence that moving to the next LTS will be straightforward, but you should avoid using non-LTS releases in production unless you can test and update the JDK with every new release.

Keeping the JDK up to date

The OpenJDK project releases quarterly patch updates in January, April, July, and October. Theses patch updates contain fixes to security vulnerabilities and critical bug fixes, as well as additional non-security bug fixes.

The main recommendation is to keep JDK installs up to date with all patch updates to ensure the latest security vulnerability fixes and other improvements are available. For example, if you use Java 11 and the JDK version used in production is 11.0.1, then you are missing more than two years of important security, stability, and performance fixes defeating the purpose of LTS releases. As patch updates between the same major version are generally backward compatible, they provide a low-risk vehicle for the potentially urgent deployment of security fixes.

Which build of Java should I use?

Java releases used to be simple - you'd download a build for a particular operating system from the Sun Microsystems website, and that was it. Today, because of the fact the OpenJDK is open source, numerous companies make available builds of the OpenJDK that are all equivalent. Some companies also offer enhanced builds of OpenJDK that offer improved performance, security, or other enhancements.

If your needs are simple and you do not require any form of support, any build of OpenJDK will be sufficient. Some distributions include:

The commonly recommended choice is Eclipse Temurin, but in general, you should choose the vendor that closely matches your environment or needs, some vendors only offer LTS builds of the OpenJDK, others even extended some non-LTS releases to be MTS (Medium Term Support) like Azul Zulu JDK 13 and 15, and others like the Oracle's OpenJDK don't even offer LTS versions (and should be avoided if you choose LTS releases).

If you are looking for a supported offering, your best choice is to choose a build from your cloud provider, such as the Microsoft OpenJDK build if you are using Azure, as these will offer the best integration and support options for you and your cloud of choice.

Ecosystem support for Java 9 and later

Oftentimes the reason a Java version choice is made is because of a dependency of our project having a hard dependency on a particular version of Java. This has often been true historically (and still holds true today to an extent) for application frameworks and other critical tooling, with their dependency on Java 8 (or, more precisely, their lack of support for Java 9 and later). Every day that goes by sees this argument become less strong, as more and more of the critical libraries and frameworks we depend on beginning to support Java 9 and later. It is beneficial every release cycle, when we are looking at updating our dependencies to identify which, if any, of our dependencies still force us back to earlier versions of Java, and to ask questions:

  • Do I still need this dependency?
  • Is there a suitable replacement for this dependency?
  • Is this dependency still being actively developed?
  • Why hasn't this dependency moved beyond Java 8?
  • Can I help to unblock this dependency, with code, bug reports, or reproducible test cases?

Because our goal is to always go to production with the latest Java LTS release, we need to be increasingly clear in our own minds on what we need to do to be at that point. If the likelihood of one of our dependencies never unblocking us is too high, we should find another path if at all possible. Falling off the LTS support window is more undesirable and will grow to become more of a technical debt the longer we wait to resolve it.