Homebrew doesn’t actually manage Java installations; it just downloads and installs them for you, leaving the actual switching to your operating system’s environment variables.

Let’s get Java installed and switch between versions.

First, we need to see what Java versions Homebrew knows about.

brew search java

This will give you a list of available Java Development Kits (JDKs). You’ll see names like openjdk, openjdk@11, openjdk@17, etc. openjdk usually refers to the latest stable version.

To install a specific version, say OpenJDK 17:

brew install openjdk@17

Homebrew will download and install it. Once it’s done, it will print some instructions. Crucially, it won’t automatically configure your system to use it.

Homebrew installs these JDKs into a directory like /usr/local/opt/openjdk@17/libexec/openjdk.jdk. Your system needs to know where to find the java executable within that directory.

The standard way to manage Java versions on macOS is by setting the JAVA_HOME environment variable. This variable tells Java-based tools (like Maven, Gradle, or even the java command itself) which JDK installation to use.

After installing openjdk@17, Homebrew will tell you something like:

==> Caveats
To install the latest version of this formula, run:
  brew install --cask adoptopenjdk
    or
  brew install openjdk@17

openjdk@17 is keg-only, which means it was not symlinked into /usr/local,
because this is an alternative version of what is already installed in
macOS.

If you need to have openjdk@17 first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc
  echo 'export JAVA_HOME="/usr/local/opt/openjdk@17"' >> ~/.zshrc

For the system Java wrappers to find this JDK, run the following:
  sudo ln -sfs /usr/local/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-17.jdk

The JAVA_HOME part is key. Let’s break down those commands:

  1. echo 'export PATH="/usr/local/opt/openjdk@17/bin:$PATH"' >> ~/.zshrc: This adds a line to your shell’s configuration file (.zshrc for Zsh, or .bash_profile for Bash) that prepends the bin directory of your chosen Java version to your system’s PATH. This makes the java command from that specific installation available directly.
  2. echo 'export JAVA_HOME="/usr/local/opt/openjdk@17"' >> ~/.zshrc: This sets the JAVA_HOME environment variable to point to the root of the JDK installation.

Important: If you’re using Bash, you’ll want to append these to ~/.bash_profile instead of ~/.zshrc. After modifying your shell’s config file, you need to either close and reopen your terminal, or run source ~/.zshrc (or source ~/.bash_profile) for the changes to take effect.

To verify, run:

java -version
echo $JAVA_HOME

You should see output indicating OpenJDK 17, and $JAVA_HOME should point to /usr/local/opt/openjdk@17.

Now, what if you have multiple versions installed, say openjdk@11 and openjdk@17? You’d follow the same process for each.

Let’s say you have both installed and want to switch to OpenJDK 11. You would remove the existing JAVA_HOME and PATH exports for OpenJDK 17 from your ~/.zshrc (or ~/.bash_profile) and add the ones for OpenJDK 11.

The Homebrew paths for these would typically be:

  • OpenJDK 11: /usr/local/opt/openjdk@11/libexec/openjdk.jdk for the symlink, and /usr/local/opt/openjdk@11/bin for the PATH.
  • OpenJDK 17: /usr/local/opt/openjdk@17/libexec/openjdk.jdk for the symlink, and /usr/local/opt/openjdk@17/bin for the PATH.

So, to switch to OpenJDK 11, you’d edit ~/.zshrc to contain:

export PATH="/usr/local/opt/openjdk@11/bin:$PATH"
export JAVA_HOME="/usr/local/opt/openjdk@11"

Then run source ~/.zshrc.

The sudo ln -sfs ... command Homebrew suggests is a system-level hook. It creates a symbolic link in a standard macOS Java location (/Library/Java/JavaVirtualMachines/). This allows macOS to list your installed JDKs correctly in System Settings > Java. While JAVA_HOME is what most tools respect, this symlink is good practice for system integration. If you switch versions, you’ll need to update this symlink as well. For OpenJDK 11, it would be:

sudo ln -sfs /usr/local/opt/openjdk@11/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk-11.jdk

This command replaces the existing link (if any) with a new one pointing to your desired version. The fs flags mean "force" (overwrite if exists) and "symbolic" (create a symlink).

The most common pitfall is forgetting to source your shell config file or restart your terminal after making changes. If java -version still shows the old version, that’s your first sign.

If you later try to install another version, like openjdk@21, and run into issues, it’s likely because the JAVA_HOME and PATH variables in your shell configuration file are still pointing to an older version, or you forgot to update the symlink in /Library/Java/JavaVirtualMachines/.

Want structured learning?

Take the full Homebrew course →