November 14, 2026 ยท Guide

Eclipse Temurin vs Oracle JDK on Windows: Which One Should Your Build Actually Point At

Half past nine on a Tuesday, and a build agent is red because JAVA_HOME points at a JDK that Oracle stopped shipping free updates for two releases ago. Nothing in the log says so. It just fails on a TLS handshake against a repo that rotated its certificate. We have fixed that exact class of failure on four different machines this year, and the root cause is always the same: nobody decided which JDK the build should point at, so the installer decided for them.

That decision deserves ten minutes of thought. Here is how we think about Eclipse Temurin vs Oracle JDK on a Windows box, from the point of view of someone who has to keep CI green and developers unblocked.

The licensing question, before anything else

Oracle JDK is free to download and use for development and testing. It is not free forever for commercial production use under the older license terms. Oracle moved to a model where production use of its builds requires a paid subscription, while the source code itself stays open through OpenJDK. Temurin is a build of that same OpenJDK source, distributed by the Eclipse Adoptium project under a permissive license with no production restrictions.

This matters on Windows because the Oracle installer is the one most people click first. It is the default result, it comes with a working java.exe, and it will happily sit on a machine for years while a legal team somewhere finds out. We have seen builds ship on Oracle JDK for two years before anyone asked the question. Sort that out before you touch JAVA_HOME.

Same source, different builds

This is the part people gloss over. Temurin and Oracle JDK are both compiled from OpenJDK source. They implement the same specification. A javac from Temurin and a javac from Oracle at the same feature release produce bytecode that behaves identically for the vast majority of code.

What differs is the packaging, the support commitment and the extra bits Oracle ships in its commercial build, things like some performance monitoring and management features aimed at enterprises. For a standard Spring service or a Gradle build on Windows, you will not notice the difference. For a shop that has built tooling around Oracle-specific flight recorder integrations or paid support SLAs, you will.

So the split is not technical quality. Both are solid. The split is what happens when something breaks at 3pm on a Friday and you need a fix or a paid human on the phone.

Installing Temurin on Windows without creating a mess

The Temurin installer is unremarkable in the best way. You download an .msi from Adoptium, run it, and it drops the JDK somewhere under Program Files\Eclipse Adoptium with a version-stamped folder name. It sets JAVA_HOME and prepends the bin directory to PATH if you ask it to. That is all we need from an installer.

Two habits we enforce on every Windows machine we touch:

  • Install to the default path. Custom paths look tidy until a script hardcodes the first one and someone installs a second JDK.
  • Let the installer handle PATH once, then leave it alone. Hand-editing the system PATH to add a second JDK is how you get the classic “works in one terminal, not the other” problem, where a user-level PATH entry shadows the system one and nobody notices for a week.

If you need multiple JDKs side by side, do not fight the installer. Use a version manager or set JAVA_HOME per project, and keep the system-level path pointing at whichever JDK you want as the sane default. The system path should be boring. Project-specific tools should be explicit.

Pointing the build at the right JDK

Here is the part that actually bites. Gradle and Maven both read JAVA_HOME, but neither respects it the way you expect once wrapper scripts get involved. The Gradle wrapper will use whatever JDK launched it, which is usually the one on PATH, not the one in JAVA_HOME. We have watched a build pass locally and fail in CI on the same commit because the local machine had Temurin 21 on PATH and the CI container had a different vendor’s 17.

The fix is to be explicit in the build file, not the environment. Pin the toolchain in Gradle:

java {
 toolchain {
 languageVersion = JavaLanguageVersion.of(21)
 }
}

And in the wrapper properties, keep the distribution version pinned. For Maven, set the compiler release in the POM and do not rely on the ambient JDK for compilation target. The environment provides a runtime. The build file provides a contract. Mixing the two is how you get “works on my machine” all over again.

On a CI agent, we go one step further and log the actual vendor and version at the start of every build:

java -version
echo %JAVA_HOME%

If a build fails and the log does not show which JDK ran, you are debugging blind. Put it in the pipeline and never wonder again.

What we actually recommend

For most Windows development and CI workloads, point at Temurin. It is the same OpenJDK source, it has no production licensing trap, the installer is clean, and multiple major distributions ship it as their default JDK package. If your company has an Oracle support contract and depends on features only the commercial build provides, stay on Oracle JDK. That is a legitimate business decision, not a technical one.

What is not legitimate is letting the installer pick for you and never revisiting the choice. That is the pattern behind most of the broken JAVA_HOME setups we clean up. The JDK is a dependency. Treat it like one: pin the version, pin the vendor, log both, and revisit when you upgrade the language level, not when a build breaks.

The build should point at one JDK, on purpose, written down somewhere a new team member can find. Whether that line says Temurin or Oracle matters less than the fact that the line exists at all.