How to Install Java 21 (JDK 21) on Windows 10 and 11
Download the Windows x64 MSI for Eclipse Temurin 21 or Amazon Corretto 21 — both are free OpenJDK builds of Java 21. During the Temurin wizard, tick "Set JAVA_HOME variable", since it is off by default. Then open a new terminal and run `java -version`; it should print 21.0.x.
The short version
Install Eclipse Temurin 21 or Amazon Corretto 21 using the Windows x64 MSI installer, tick the box that sets JAVA_HOME, open a new terminal, and run java -version. If it prints 21.0.x, you are done. Everything below explains why those choices, and what to do when the version printed is not 21.
1. "Java 21" is not one download
This trips up almost everyone on their first install. Java SE 21 is a specification — a document describing the language and the standard library. Several companies build shippable software from it, and each build is a JDK ("Java Development Kit": the compiler, the runtime, and the command-line tools in one package). JDK 21 is a Long-Term-Support release, generally available since 19 September 2023, and it delivered 15 JEPs including Virtual Threads (JEP 444), Pattern Matching for switch (JEP 441) and Record Patterns (JEP 440).
Those features are in every JDK 21. Temurin 21 and Oracle JDK 21 compile identical code. What differs is the licence and how long you get free security patches.
| Distribution | Licence | Free updates until |
|---|---|---|
| Oracle JDK 21 | Oracle NFTC | September 2026 |
| Eclipse Temurin 21 | GPLv2 + Classpath Exception | at least 2029 |
| Amazon Corretto 21 | No-cost OpenJDK build — Amazon's terms | at least October 2029 |
| Microsoft Build of OpenJDK 21 | OpenJDK build — Microsoft's terms | at least September 2031 |
On the licence question people actually mean: yes, Oracle JDK 21 is free, including for commercial and production use, under the No-Fee Terms and Conditions. The catch is the update window. Oracle's free NFTC updates for an LTS release stop one year after the next LTS ships, and per Oracle's support roadmap, JDK 25 arrived in September 2025 — so free Oracle JDK 21 updates run out in September 2026, after which further patches need a Java SE Subscription. Adoptium commits to a minimum of four years for an LTS, Amazon promises quarterly Corretto 21 updates through at least October 2029, and Microsoft's Java 21 builds are supported until at least September 2031. If you are a student who will still be using this machine in three years, or a developer who does not want procurement asking questions about a licence later, pick Temurin or Corretto. The GPLv2-with-Classpath-Exception licence that OpenJDK builds such as Temurin use is specifically designed so linking your application against the runtime creates no obligations on your own code.
Architecture: pick x64 on a normal PC or laptop. Pick AArch64 only if you have a Windows-on-ARM device — and note that Oracle's JDK 21 Windows downloads are x64 only, so ARM users must use Temurin, Microsoft or Azul Zulu. There is no meaningful 32-bit option: JEP 449 deprecated the Windows 32-bit x86 port for removal in JDK 21, which makes JDK 21 the practical end of 32-bit x86 Windows builds.
JDK or JRE? JDK. Oracle no longer ships a standalone JRE (the runtime-only package), and you need javac to compile anything. Oracle's certified configurations for JDK 21 on x64 cover Windows 11, Windows 10, and Windows Server 2016/2019/2022.
2. Route 1 — the MSI installer
Which terminal? Either Command Prompt or PowerShell will do, but they are not interchangeable for every command below, so each code block is labelled with the one it expects — powershell or bat (Command Prompt). Where the two differ, the prose says so. If you are unsure which you have open, Windows Terminal defaults to PowerShell.
Download the Windows x64 .msi from the Temurin 21 releases page. Adoptium publishes SHA-256 checksums next to each file; verify yours before running it. In the commands below, replace 21.0.x_y with the actual build number of the file you downloaded (the filename on disk carries it, for example 21.0.5_11) — pasting the placeholder verbatim will only produce a "path does not exist" error:
Get-FileHash .\OpenJDK21U-jdk_x64_windows_hotspot_21.0.x_y.msi
Get-FileHash defaults to SHA256, so no extra arguments are needed. In cmd.exe the equivalent is certutil -hashfile <file> SHA256. Compare the output to the published value.
Run the MSI. Oracle documents that installing the JDK on Windows requires Administrator privileges, so run the installer from an account that has them.
Stop at the Custom Setup screen. This is the single step most guides skip. The Temurin MSI offers four features — Add to PATH, Associate .jar, Set JAVA_HOME variable, and JavaSoft (Oracle) registry keys — and by default only the first two are installed. JAVA_HOME is off. Click it and choose to install it. Maven will not run without it (its install guide requires JAVA_HOME), and most IDE and build-tool integrations read it too. The JavaSoft (Oracle) registry keys option is likewise off by default; tick it only if something specifically asks for it.
Temurin installs to C:\Program Files\Eclipse Adoptium\jdk-21.x.y-hotspot by default; Oracle's installer uses C:\Program Files\Java\jdk-21.
Amazon Corretto's Windows MSI sets JAVA_HOME and adds bin to PATH itself, with no checkbox to remember — which is a fair reason to prefer it if you are walking someone else through this over a phone call.
Setting up a college lab or a team of machines? Both installers script cleanly (again, substitute the real build number for 21.0.x_y). This one is Command Prompt, not PowerShell — the trailing ^ is cmd.exe's line continuation, and pasting it into PowerShell fails to parse:
msiexec /i OpenJDK21U-jdk_x64_windows_hotspot_21.0.x_y.msi ^
ADDLOCAL=FeatureMain,FeatureEnvironment,FeatureJarFileRunWith,FeatureJavaHome ^
INSTALLDIR="C:\Program Files\Eclipse Adoptium\jdk-21" /quiet
In PowerShell, put it on a single line instead, or swap each ^ for a backtick.
FeatureEnvironment is the PATH entry and FeatureJavaHome is the variable. Oracle's .exe uses a different syntax: jdk-21_windows-x64_bin.exe /s INSTALLDIR=C:\test.
3. Route 2 — winget, Route 3 — the ZIP
Windows Package Manager ships with Windows 11 and with a current App Installer on Windows 10:
winget install EclipseAdoptium.Temurin.21.JDK
## or
winget install Microsoft.OpenJDK.21
Fast, but it does not present the MSI's feature selection, so do not assume JAVA_HOME was set for you. Open a new terminal, run echo %JAVA_HOME%, and if it comes back empty, set it yourself using section 4.
The ZIP is the route when you want to place and configure the JDK entirely yourself. Extract it somewhere you own, such as C:\Java\jdk-21.0.x. Adoptium is clear that the ZIP configures nothing — there is no installer to set variables, so you must set JAVA_HOME to the extracted JDK directory yourself and add %JAVA_HOME%\bin to PATH. That is the point: you decide which one is active.
4. JAVA_HOME and PATH, set correctly
Two variables, two different values, and mixing them up is the most common failure:
JAVA_HOME= the JDK root directory, e.g.C:\Java\jdk-21.0.x. Not\bin.PATHgets%JAVA_HOME%\bin, the folder that actually containsjava.exe,javac.exe,jar,javadoc,jshellandjlink.
GUI route: run SystemPropertiesAdvanced.exe, click Environment Variables, then New → name JAVA_HOME, value the JDK root. Then select Path, Edit, New, and add %JAVA_HOME%\bin. Use the User variables section if you are not an administrator — it applies only to your account and needs no elevation. System variables apply machine-wide and need an elevated session.
Command line route:
setx JAVA_HOME "C:\Java\jdk-21.0.x"
Two traps worth stating outright, both from Microsoft's setx reference. First, setx does not change the shell you typed it in — open a new prompt. Second, setx truncates values over 1024 characters, and a lived-in Windows PATH is often longer than that, so setx PATH ... can silently destroy it. Add the PATH entry through the GUI editor, or in PowerShell with [Environment]::SetEnvironmentVariable. setx /M writes machine scope and needs an elevated prompt.
Order matters: Oracle documents that the JDK bin directory must precede other Java entries so its java.exe is found first. And keep the two in sync — Gradle resolves its JVM by checking JAVA_HOME first, falling back to java on PATH, so a mismatch means your build and your terminal are using different Javas.
5. Verify — and fix a wrong version
Open a new terminal, then:
java -version
javac --version
echo %JAVA_HOME%
where java
In PowerShell use $env:JAVA_HOME instead of echo %JAVA_HOME%. Expect something of the form 21.0.x. Running javac --version as well is what confirms the compiler is on PATH and not just a runtime. Note that java -version writes to standard error while java --version writes to standard output — worth knowing before you pipe either command into something. The JDK's bin directory also carries jshell, the JShell REPL — a read-eval-print loop, meaning an interactive prompt where you type a Java expression and see its result immediately.
Reading the number: the version format is $FEATURE.$INTERIM.$UPDATE.$PATCH (Runtime.Version), so 21.0.5 is Java 21, update 5. Always download the newest 21.0.x rather than the original GA build — updates carry security fixes.
java -version still shows an old JDK
Run where java. It lists every java.exe on PATH in resolution order, and the first line is the one winning:
C:\Windows\System32\java.exe
C:\Program Files\Eclipse Adoptium\jdk-21.0.x-hotspot\bin\java.exe
That first line is a leftover from an earlier Java installation. C:\Windows\System32 usually appears early in PATH, so a stale java.exe sitting there is found before your new JDK. Fix it by moving %JAVA_HOME%\bin above the offending entry in the Path editor, or by removing the stale entry entirely. A stale C:\ProgramData\Oracle\Java\javapath entry behaves the same way.
'javac' is not recognized as an internal or external command
Three causes, in order of likelihood: bin never made it onto PATH; JAVA_HOME points at ...\jdk-21.0.x\bin instead of the JDK root, so %JAVA_HOME%\bin expands to a folder that does not exist; or you never opened a new terminal after setting the variables.
UnsupportedClassVersionError: class file version 65.0
JDK 21's javac emits class file major version 65 by default. This error means the code was compiled by 21 but is running on an older JVM — exactly what happens when JAVA_HOME points at 21 (so your build tool compiles with 21) while PATH resolves java to something older. Fix the PATH order. If you genuinely need to target an older runtime, javac --release accepts values 8 through 21:
javac --release 17 App.java
One last thing to check on an inherited machine: if JDK_JAVA_OPTIONS is set, its contents are prepended to every java command line. Leftover flags in there produce behaviour that looks impossible until you run echo %JDK_JAVA_OPTIONS% and find them.
Elsewhere on this blog
Not about installing Java, but about the same habit of checking what a system actually resolves rather than what you assume it resolves:
Frequently asked questions
- Do I need to uninstall my old Java before installing JDK 21?
- No — installing JDK 21 does not require removing an older one. What you must do is make sure PATH resolves to the version you want — run `where java` and confirm the JDK 21 bin directory is listed first. The usual problem is not the old JDK itself but a leftover launcher stub in C:\Windows\System32 or a stale Oracle javapath entry sitting earlier on PATH.
- Can I install JDK 21 without administrator rights?
- The ZIP package is the route to try instead of the MSI. Extract it to a folder your account can write to, such as C:\Java\jdk-21.0.x, then set JAVA_HOME and add %JAVA_HOME%\bin to PATH as User variables in the Environment Variables dialog — machine scope is what needs an elevated prompt, as setx /M does. Adoptium documents that the ZIP configures nothing for you, so both variables are your responsibility.
- Which JDK 21 should I use for Spring Boot or college coursework?
- Eclipse Temurin 21 or Amazon Corretto 21. Both are no-cost OpenJDK builds — Temurin under GPLv2 with the Classpath Exception — both have update commitments running to at least 2029, and neither creates a licensing conversation later. The language features and APIs are identical to Oracle JDK 21, so nothing in your coursework or your Spring Boot project behaves differently.
- How do I switch between JDK 21 and another installed JDK?
- Change JAVA_HOME to the other JDK's root directory and keep %JAVA_HOME%\bin as your PATH entry rather than a hardcoded path. Then only one variable needs editing per switch, and tools that read JAVA_HOME follow along automatically. Remember that setx does not affect the shell you ran it in, so open a new terminal after each change.
- Why does my build tool use a different Java version than my terminal?
- Because they resolve the JVM differently. Gradle checks JAVA_HOME first and only falls back to java on PATH, while your terminal just uses PATH. If the two point at different JDKs you get compile-and-run mismatches — most visibly an UnsupportedClassVersionError mentioning class file version 65.0, meaning JDK 21 compiled the code but an older JVM tried to run it.
- Is there a 32-bit JDK 21 for Windows?
- Not one you should use. JEP 449 deprecated the Windows 32-bit x86 port for removal in JDK 21, which makes JDK 21 the practical end of 32-bit x86 Windows builds. Install the x64 build on a normal PC, or the AArch64 build on a Windows-on-ARM device — noting that Oracle's JDK 21 Windows downloads are x64 only, so ARM users need Temurin, Microsoft Build of OpenJDK or Azul Zulu.
References
- JDK 21 Project page (schedule, features, JEP list)OpenJDK
- JEP 449: Deprecate the Windows 32-bit x86 Port for RemovalOpenJDK
- Installation of the JDK on Microsoft Windows Platforms (JDK 21)Oracle
- Java Downloads — JDK 21 Windows packagesOracle
- Oracle No-Fee Terms and Conditions (NFTC)Oracle
- Oracle Java SE Support RoadmapOracle
- JDK 21 Certified System ConfigurationsOracle
- java command — JDK 21 Tool SpecificationsOracle
- javac command — JDK 21 Tool SpecificationsOracle
- JDK 21 Tool Specifications indexOracle
- java.lang.Runtime.Version (Java SE 21 API)Oracle
- The Java Virtual Machine Specification, Java SE 21 — Chapter 4: The class File FormatOracle
- Installing Temurin on WindowsEclipse Adoptium
- Temurin 21 Windows releases (downloads and checksums)Eclipse Adoptium
- Adoptium Support and release policyEclipse Adoptium
- GNU General Public License, version 2, with the Classpath ExceptionOpenJDK
- What is Amazon Corretto 21?AWS
- Amazon Corretto — Install on WindowsAWS
- Amazon Corretto FAQsAWS
- Download the Microsoft Build of OpenJDKMicrosoft
- Install the Microsoft Build of OpenJDKMicrosoft
- setx — Windows Commands referenceMicrosoft
- Windows Package Manager (winget) documentationMicrosoft
- Get-FileHash (Microsoft.PowerShell.Utility)Microsoft
- Installing Apache MavenApache Maven
- Gradle Daemon / JVM resolutionGradle
- Azul Zulu Builds of OpenJDK — Java 21 downloads for WindowsAzul