Question
How can you change the default Java version on macOS so that terminal commands like java and javac use a specific JDK installation?
Short Answer
By the end of this page, you will understand how macOS chooses a Java version, how to check installed JDKs, and how to change the default JDK temporarily or permanently using JAVA_HOME and the java_home tool.
Concept
On macOS, the Java version used by commands such as java, javac, and many build tools is usually controlled by the JAVA_HOME environment variable and the system's installed JDK locations.
A JDK (Java Development Kit) includes tools for developing and running Java programs. If you install multiple versions, such as Java 8, 11, 17, or 21, you may need to choose which one your shell or project should use.
macOS provides a helpful command-line utility called java_home that can locate installed JDKs. Instead of manually typing long installation paths, you can use this tool to select a version safely.
This matters because different projects often require different Java versions:
- Older enterprise applications may require Java 8
- Some Android or backend projects may use Java 11 or 17
- Newer frameworks may expect Java 21
- Build tools like Maven, Gradle, and IDEs often depend on the correct JDK
Changing the default Java version usually means one of these:
- Setting it for the current terminal session only
- Setting it permanently in your shell config file
- Setting it for one project or script only
The most common and reliable approach on macOS is to set JAVA_HOME using /usr/libexec/java_home.
Mental Model
Think of Java versions like different toolboxes stored in your garage.
- Each installed JDK is one toolbox
JAVA_HOMEis the label telling your system which toolbox to open by default- The
javacommand uses that label to find the correct tools
If you change the label, your terminal starts using a different toolbox without uninstalling the others.
So you are not replacing Java entirely. You are choosing which installed Java version should be used first.
Syntax and Examples
The most important commands are:
/usr/libexec/java_home -V
This lists all installed JDKs.
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
This sets Java 17 for the current shell session.
java -version
javac -version
These confirm which Java version is currently active.
Example: switch to Java 17 temporarily
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH="$JAVA_HOME/bin:$PATH"
java -version
Example output might be:
openjdk version "17.0.10" 2024-01-16
Example: make Java 21 the default permanently
If you use zsh on modern macOS, add this to ~/.zshrc:
export JAVA_HOME=$(/usr/libexec/java_home -v 21)
export PATH="$JAVA_HOME/bin:"
Step by Step Execution
Consider this example:
export JAVA_HOME=$(/usr/libexec/java_home -v 11)
export PATH="$JAVA_HOME/bin:$PATH"
java -version
Here is what happens step by step:
/usr/libexec/java_home -v 11asks macOS to find an installed JDK that matches version 11.- The command returns a path such as:
/Library/Java/JavaVirtualMachines/temurin-11.jdk/Contents/Home export JAVA_HOME=...stores that path in theJAVA_HOMEenvironment variable.export PATH="$JAVA_HOME/bin:$PATH"puts that JDK'sbindirectory at the front of your command search path.- When you run
java -version, your shell findsjavainside the selected JDK first. - The terminal prints the Java 11 version, confirming the switch worked.
Small trace example
/usr/libexec/java_home -V
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
echo $JAVA_HOME
java -version
Possible flow:
Real World Use Cases
Changing the default Java version on macOS is common in real development work.
Common situations
- Running old projects: A legacy application may only build correctly with Java 8.
- Using modern frameworks: New Spring Boot or backend services may require Java 17 or later.
- Working across multiple repositories: One project uses Java 11, another uses Java 21.
- CI debugging locally: You may need your local machine to match the Java version used in a deployment pipeline.
- Build tool compatibility: Maven, Gradle, and Ant often read
JAVA_HOME. - IDE integration: IntelliJ IDEA, Eclipse, and VS Code may use system Java settings or project-specific JDKs.
Script and automation examples
- A shell script can set a specific JDK before running a build
- A project setup guide can tell teammates which version to export
- A deployment script can verify
java -versionbefore packaging an application
Real Codebase Usage
In real projects, developers rarely change Java versions randomly. They usually do it in structured ways.
Common patterns
- Project-specific setup: A project's README may instruct developers to use Java 17.
- Shell profile defaults: Developers set a personal default version in
~/.zshrcor~/.bash_profile. - Temporary overrides: Before running one build, they export a different
JAVA_HOMEin that terminal only. - Validation checks: Scripts often verify the version:
java -version
- Guard clauses in scripts: A setup script may stop early if the wrong Java version is active.
if ! java -version 2>&1 | grep '17' >/dev/null; then
echo "Java 17 is required"
exit 1
fi
- Environment-based configuration: Teams avoid hardcoding absolute JDK paths when possible and use
java_homefor portability.
Why JAVA_HOME is preferred
Many Java tools look for JAVA_HOME directly. Even if works, some tools can still fail if is missing or points to the wrong JDK.
Common Mistakes
Here are some beginner mistakes that often cause confusion.
1. Setting JAVA_HOME to the wrong path
Broken example:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-17.jdk
This may be incomplete for many tools. The JDK home usually ends with /Contents/Home on macOS.
Better:
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
2. Forgetting to reload the shell config
If you add lines to ~/.zshrc but do not reload it, the current terminal will not see the change.
source ~/.zshrc
3. Updating JAVA_HOME but not PATH
Sometimes java still points to another location because PATH is unchanged.
Use both:
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH=
Comparisons
| Approach | What it does | Best for | Notes |
|---|---|---|---|
export JAVA_HOME=$(/usr/libexec/java_home -v 17) | Sets the active JDK using macOS lookup | Most users on macOS | Recommended and portable |
| Hardcoded JDK path | Points directly to one installation | Special cases | More fragile if paths change |
| Temporary terminal setting | Changes Java only for the current shell | Testing and one-off builds | Disappears when terminal closes |
| Shell profile setting | Changes Java for future terminal sessions | Personal default setup | Requires reload or new terminal |
JAVA_HOME vs PATH
Cheat Sheet
Check installed Java versions
/usr/libexec/java_home -V
Set Java temporarily for current terminal
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH="$JAVA_HOME/bin:$PATH"
Verify active version
java -version
javac -version
echo $JAVA_HOME
Make Java default permanently for zsh
Add to ~/.zshrc:
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH="$JAVA_HOME/bin:$PATH"
Reload:
source ~/.zshrc
Common files
~/.zshrcforzsh- for
FAQ
How do I check which Java version is currently active on macOS?
Run:
java -version
echo $JAVA_HOME
This shows the active runtime version and the selected JDK path.
How do I list all installed JDK versions on macOS?
Use:
/usr/libexec/java_home -V
This prints all detected Java installations.
How do I switch Java versions only for the current terminal session?
Run:
export JAVA_HOME=$(/usr/libexec/java_home -v 17)
export PATH="$JAVA_HOME/bin:$PATH"
That change lasts until the terminal is closed.
How do I make a Java version the default permanently?
Add the export lines to your shell config file such as ~/.zshrc, then reload it with source ~/.zshrc.
Why is java -version correct but my build tool still fails?
Some tools use JAVA_HOME directly. Make sure JAVA_HOME points to the correct JDK, not just that is on your .
Mini Project
Description
Create a small shell setup that lets you switch between installed Java versions on macOS and verify the result. This mirrors real development workflows where different projects require different JDK versions.
Goal
Build a reusable terminal helper that switches to a chosen Java version and confirms that the correct JDK is active.
Requirements
- List installed Java versions on the machine
- Create a shell function that accepts a Java version number
- Set both
JAVA_HOMEandPATHbased on that version - Print the selected
JAVA_HOME - Verify the active version with
java -version
Keep learning
Related questions
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.
Convert a Java Stack Trace to a String
Learn how to convert a Java exception stack trace to a string using StringWriter and PrintWriter, with examples and common mistakes.