How to Install Java 17 on Windows, Mac and Linux

Java 17 is a Long-Term Support release (September 2021) still widely deployed in production. Installing it is straightforward on all platforms via package managers or the Temurin installer.

Windows

winget (quickest):

winget install EclipseAdoptium.Temurin.17.JDK

MSI installer:

  1. Go to adoptium.net/temurin/releases and select Java 17, Windows, x64, JDK.
  2. Download the .msi and run it with admin rights.
  3. Enable Add to PATH and Set JAVA_HOME during setup.
  4. Open a new terminal and verify:
java -version
# openjdk version "17.0.x" ...

macOS

brew install openjdk@17

Homebrew prints a symlink hint β€” run it so macOS finds the JDK:

sudo ln -sfn $(brew --prefix)/opt/openjdk@17/libexec/openjdk.jdk \
    /Library/Java/JavaVirtualMachines/openjdk-17.jdk

Then set it as active in your shell:

export JAVA_HOME=$(/usr/libexec/java_home -v 17)
java -version

Add the export line to ~/.zshrc to persist it.

Ubuntu / Debian

sudo apt update
sudo apt install openjdk-17-jdk
java -version

Fedora / RHEL / CentOS Stream

sudo dnf install java-17-openjdk-devel
java -version

Arch Linux

sudo pacman -S jdk17-openjdk
sudo archlinux-java set java-17-openjdk

Running Java 17 and Java 21 side by side

Install both JDKs. On macOS, /usr/libexec/java_home -v 17 or -v 21 points at the right installation. On Linux, sudo update-alternatives --config java lets you pick the default. On Windows, change JAVA_HOME and ensure %JAVA_HOME%\bin is first in PATH.

Why Java 17 and not 21?

Some frameworks (older Spring Boot 2.x, certain application servers) require Java 17 or only have been tested up to 17. If you are starting fresh, prefer Java 21 β€” it adds virtual threads and more pattern matching. If a dependency constrains you to 17, install 17.

Java 17 notable features

  • Sealed classes β€” restrict which classes can extend or implement a type, enabling exhaustive pattern matching.
  • Records (finalised) β€” compact immutable data carriers.
  • Pattern matching for instanceof β€” if (obj instanceof String s) { ... } without the explicit cast.
  • Text blocks β€” multi-line strings with """ delimiter.
  • Strong encapsulation of JDK internals β€” sun.* APIs no longer accessible by default.