Every mainstream Java runtime is built from the same OpenJDK source. Eclipse Temurin, Amazon Corretto, Azul Zulu, the Microsoft Build of OpenJDK, the Red Hat build, BellSoft Liberica, SAP SapMachine and Oracle JDK all compile HotSpot and the class library from that code, so your application almost always behaves the same on each. Yet the choice still matters, because a vendor decides the licence you run under, how long you get security fixes, which platforms and optional components exist, and who answers when a production JVM crashes.
This page explains where vendor builds come from, what genuinely differs between them, how to find out exactly what your fleet runs, and how to choose and switch with low risk. Support dates and licence terms change; the figures below were checked against the vendors' own pages on 2026-10-03.
Where a vendor build comes from
New features land in the OpenJDK mainline repository and ship every six months as a feature release. When a release ships, maintenance continues in an update project (for example jdk21u and jdk25u), where fixes are backported and released quarterly, typically on the third Tuesday of January, April, July and October; the October 2026 update is due on the third Tuesday, 20 October. Vendors take those update tags, apply their own build configuration and sometimes extra patches, test, and publish binaries. The release train itself is covered in Java LTS releases.
Long-term support is a vendor promise, not an OpenJDK property. After the first months of an update project, maintenance is led by vendor engineers, and each vendor decides how long it will keep publishing builds for a release. That is why two vendors can support the same LTS version for different lengths of time.
What genuinely differs
| Dimension | What varies | Why you care |
|---|---|---|
| Licence | GPLv2 with Classpath Exception for most builds; Oracle JDK uses its own terms | Whether production use costs money |
| Update horizon | How many years of free quarterly fixes per LTS | When you are forced to upgrade |
| Platforms | OS, CPU architecture, musl or glibc builds | Alpine images, ARM servers, older OSes |
| Optional components | JavaFX bundles, CRaC-enabled builds, Shenandoah | Features that exist in one build and not another |
| Extra patches | Some vendors ship backports ahead of upstream | Fixes you may lose when switching |
| Certification | Whether the build passed the Java SE TCK | Spec compatibility evidence |
| Support | Paid SLAs, response times, custom fixes | Who you call during an outage |
Two more points. First, the VM is not always HotSpot: IBM Semeru Runtimes use the Eclipse OpenJ9 VM, which has different tuning flags and memory behaviour, so treat it as a different runtime, not just a different vendor. Second, GraalVM distributions add an alternative JIT and native-image tooling on top of a JDK; see GraalVM architecture. Everything else on this page is about HotSpot-based builds.
Optional components are where surprises hide. Shenandoah is built into most OpenJDK distributions but Oracle's JDK builds have not included it, so a flag that works on Temurin can stop the JVM from starting on Oracle JDK. JavaFX is separate from the JDK, but some vendors ship bundles that include it; Amazon ended JavaFX support in Corretto 8 on 31 March 2026. CRaC support for fast startup ships in specific builds from vendors such as Azul and BellSoft rather than in every distribution; see CRaC.
Licensing, and why October 2026 matters
Most vendor builds are free to use in production under the OpenJDK licence, GPLv2 with the Classpath Exception, which does not affect your application's licence. Oracle is different in two ways. Oracle's OpenJDK builds on jdk.java.net are GPL but are updated only for the six months of each feature release, so they are not an LTS option. Oracle JDK, the commercial-branded build, ships under the Oracle No-Fee Terms and Conditions (NFTC) for a limited window and then under the Java SE OTN licence, which requires a paid subscription for most production use.
For JDK 21, Oracle states that updates through the September 2026 release are under NFTC and updates from the October 2026 Critical Patch Update are planned under OTN. If you run Oracle JDK 21 and simply apply the next quarterly patch, you move onto licence terms that may require a subscription. JDK 25 updates are under NFTC until September 2028. The practical options are: buy the subscription, move to JDK 25 and plan the next hop before 2028, or switch to another vendor's 21 build, which for most applications is the cheapest and least disruptive.
Support horizons you can plan against
Each vendor publishes its own calendar. These are the dates listed on 2026-10-03 for the two most common free builds; check the vendor pages again before planning, as they are extended from time to time.
| Version | Eclipse Temurin (at least until) | Amazon Corretto (end of life) |
|---|---|---|
| 8 | December 2030 | December 2030 |
| 11 | October 2027 | January 2032 |
| 17 | October 2027 | October 2029 |
| 21 | December 2029 | October 2030 |
| 25 | September 2031 | October 2032 |
| 27 (non-LTS) | March 2027 | April 2027 |
Azul, Microsoft, Red Hat, BellSoft and SAP publish their own roadmaps, and paid tiers can extend coverage. The pattern to notice is that horizons differ by years for the same version, so the vendor choice for an old version like 11 or 17 is mostly a choice of how long you can postpone the upgrade. Non-LTS releases get roughly six months from everyone; run them only if you will upgrade every six months.
A horizon only helps if you actually take the updates. Treat each quarterly release as a routine change: subscribe to your vendor's release announcements, let a scheduled job rebuild base images when the new tag appears, run the test suite and a canary, and roll the fleet within a week or two. Security fixes in a quarterly update are public the day it ships, so a runtime that lags by months is exposed whatever its vendor promises. Measure lag as a number, such as days since the newest available update, rather than as a feeling.
Know what you run
Fleets drift. Base images, developer laptops, build agents and vendor appliances each bring their own JDK, and the java -version banner alone does not always name the vendor clearly. Two sources are reliable. The system properties report the vendor and full runtime version, and every modern JDK image carries a release file whose IMPLEMENTOR and JAVA_VERSION_DATE fields tell you who built it and how old its patch level is.
# What is this runtime, really?
java -XshowSettings:properties -version 2>&1 | grep -E 'java\.(vendor|vm\.vendor|runtime\.version|vm\.name) '
cat "$JAVA_HOME/release" # IMPLEMENTOR, IMPLEMENTOR_VERSION, JAVA_VERSION, JAVA_VERSION_DATE
# Does this build include an optional feature you rely on?
java -XX:+UseShenandoahGC -version # fails at startup if the collector was not built in
java --list-modules | grep javafx # only "full" or FX-bundled builds include JavaFX
# Pin the vendor in builds as well as at runtime
# Gradle toolchain: vendor = JvmVendorSpec.ADOPTIUM (or AMAZON, AZUL, ...)
# actions/setup-java: distribution: 'temurin' (or 'corretto', 'zulu', ...)
# Dockerfile: FROM eclipse-temurin:21-jre@sha256:<digest>To audit many hosts or images, read the release files rather than starting a JVM per install. The script below flags runtimes more than about one quarter behind and every Oracle-built runtime for a licence check. Oracle's GPL builds also report Oracle Corporation, which is why it flags rather than concludes.
#!/usr/bin/env python3
"""Inventory JDKs: vendor, version and patch age from each $JAVA_HOME/release file."""
import datetime, pathlib, sys
def read_release(java_home):
info = {}
for line in (pathlib.Path(java_home) / "release").read_text().splitlines():
if "=" in line:
key, value = line.split("=", 1)
info[key] = value.strip().strip('"')
return info
def assess(java_home, today=None):
today = today or datetime.date.today()
r = read_release(java_home)
vendor = r.get("IMPLEMENTOR", "unknown")
version = r.get("JAVA_VERSION", "?")
built = r.get("JAVA_VERSION_DATE")
age = (today - datetime.date.fromisoformat(built)).days if built else None
flags = []
if age is None or age > 100: # older than one quarterly update plus slack
flags.append("behind on quarterly updates")
if vendor == "Oracle Corporation":
flags.append("Oracle build: check licence (NFTC, OTN or jdk.java.net GPL)")
return f"{java_home}: {vendor} {version} built {built} -> {', '.join(flags) or 'ok'}"
for home in sys.argv[1:]:
print(assess(home))
Worked example: leaving Oracle JDK 21 before the October update
A team runs forty services on Oracle JDK 21, last patched with the July 2026 update, in containers and wants to keep free updates without changing Java version. They choose Temurin 21 because their base images already use Ubuntu and the official eclipse-temurin images fit their build. The plan has five steps.
- Inventory: run the release-file audit over every image and host; find the few that use Oracle-only paths or flags.
- Swap the base image in one low-risk service, pinned by digest, keeping the same 21 update level so only the vendor changes.
- Diff behaviour: compare startup flags, the default trust store (vendors maintain their own CA certificate sets, so test outbound TLS), fonts for any server-side rendering, and time-zone data.
- Compare performance with the same heap and GC settings over a full load test; expect differences within noise, and investigate anything larger.
- Roll out by service, then make the vendor explicit in Gradle or Maven toolchains and CI so it cannot drift back.
The work is mostly verification, not code change. The real risk is the long tail: a forgotten build agent or vendor appliance still pulling Oracle JDK updates. Container specifics, including memory sizing, are in Java containerization.
How to choose
| Situation | Reasonable default | Reason |
|---|---|---|
| No special needs, any cloud | Temurin | Vendor-neutral, widely packaged, TCK and AQAvit tested |
| Mostly on AWS | Corretto | Long horizons, AWS support, Amazon Linux packaging |
| Azure or Microsoft stack | Microsoft Build of OpenJDK | Microsoft-supported images and guidance |
| RHEL-based estate | Red Hat build of OpenJDK | Covered by the RHEL subscription and packaging |
| Need JavaFX, CRaC or paid long support | Azul or BellSoft | Bundles and commercial tiers |
| Already pay Oracle | Oracle JDK | Use the support you own; watch licence dates |
Above all, choose one per estate. A single vendor with a known calendar is worth more than the best vendor chosen differently by every team.
Failure modes
- Accidental licence change: an automated update moves Oracle JDK onto OTN terms.
- Silent end of updates: a vendor's horizon passes and images keep building on an unpatched JDK.
- Missing feature: a GC, JavaFX or CRaC flag fails on a different build.
- Trust store drift: outbound TLS breaks because CA sets differ between vendors.
- Floating tags:
latestor major-only image tags change vendor patch level without review. - Mixed fleets: bug reports cannot be reproduced because laptops, CI and production run different builds.
What to do next
- Inventory every JDK in images, hosts and CI, recording vendor, version and build date.
- List every Oracle JDK install and decide, before the October 2026 update, whether to subscribe, move to JDK 25 or switch vendor.
- Choose one default vendor and record its support dates for each Java version you run.
- Pin images by digest and toolchains by vendor so builds cannot drift.
- Add a CI check that fails when a runtime is more than one quarterly update behind.
- Test GC flags, optional modules and outbound TLS whenever you change vendor.
- Trim the runtime you ship with jlink once the vendor is fixed.