Java

There is no AI here. All content is human-authored and tested for accuracy.

Set JAVA_HOME on Mac

How to set JAVA_HOME on Mac. Find your JDK path, export JAVA_HOME in zsh, switch Java versions, and fix common macOS Java errors. Required for Maven, Gradle, and other tools.

The JAVA_HOME environment variable tells developer tools where to find Java on your Mac.

Apple's macOS is designed so regular users can run Java applications as soon as a JDK is installed without touching any shell settings. However, for development work, many tools look for a JAVA_HOME environment variable to locate the JDK. It is not set automatically by an installer or a Homebrew installation script. As a result, developers often need to set JAVA_HOME so that development tools can find the JDK rather than relying on macOS’s Java system launcher behavior.

This guide shows you how to find your Java installation location, set JAVA_HOME permanently, and verify everything works. You will also learn how to troubleshoot common problems and switch between Java versions. If you have not installed Java yet, see Download Java for Mac.

Before you get started

You'll need a terminal application to set JAVA_HOME and develop with Java. Apple includes the Mac terminal but I prefer Warp Terminal. Warp is an easy-to-use terminal application, with AI assistance to help you learn and remember terminal commands. Download Warp Terminal now; it's FREE and makes coding easier when working with Java.

What is JAVA_HOME?

Commands that run in a terminal application get system information from environment variables. Apple's macOS uses Zsh, the Z shell, by default in any terminal application. You can set environment variables in the ~/.zprofile or ~/.zshrc shell configuration files. See the article Mac Shell Configuration for instructions about editing shell configuration files.

JAVA_HOME is an environment variable that many developer tools expect to find, showing the location of the root directory of your Mac's JDK installation. JAVA_HOME is not set automatically. As a developer, you must set JAVA_HOME in the ~/.zprofile shell configuration file before you use any tools that need it.

JAVA_HOME should point to the root directory of your JDK installation, not the bin folder containing the Java executable inside it. A typical JAVA_HOME path looks like this:

/Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home

The path /Library/Java/JavaVirtualMachines/ is the standard location for any JDK package you've installed. The path contains the distribution name for the vendor JDK you've installed, such as temurin-25.jdk. The path ends with Contents/Home. This directory contains subdirectories like bin (executables), lib (libraries), and conf (configuration files). Build tools navigate from JAVA_HOME to these subdirectories as needed.

A common mistake is setting JAVA_HOME to the bin directory. This causes errors like "JAVA_HOME is not defined correctly." Always point to the JDK root at the Contents/Home level. not the bin folder inside it.

Why JAVA_HOME Matters

Many developer tools require JAVA_HOME to locate the JDK:

  • Maven and Gradle check JAVA_HOME to find the Java compiler and runtime
  • Apache Ant needs either JAVA_HOME or JRE_HOME to run builds
  • Application servers like Tomcat use JAVA_HOME to locate the JVM
  • IDEs can read JAVA_HOME as a default SDK location
  • CI/CD pipelines reference JAVA_HOME for consistent builds across environments

Without JAVA_HOME, Maven displays an error like "The JAVA_HOME environment variable is not defined correctly." Gradle may complain that it cannot find Java. Setting JAVA_HOME once eliminates these problems.

Do You Need JAVA_HOME?

If you only run Java applications (not develop them), you may not need JAVA_HOME. However, if you use Maven, Gradle, or any professional build tool, JAVA_HOME is required. Setting it is a best practice for any Java development environment.

You may be surprised that a java command works in the terminal as soon as you install Java. Here's why a java command works but the JAVA_HOME setting is still needed. The installer puts a JDK bundle into a standard location such as /Library/Java/JavaVirtualMachines/.... The macOS built‑in Java launcher is available at /usr/bin/java, which is on the default PATH, so typing java in Terminal “just works” for running Java programs. This default setup hides details like where the JDK lives and how java is resolved. For development work, though, many tools look for a JAVA_HOME environment variable to locate the JDK directly, and that variable is not set automatically by the installer or by a Homebrew cask. As a result, developers typically still need to define JAVA_HOME rather than relying on macOS’s implicit system launcher behavior.

JAVA_HOME vs. PATH

These two environment variables serve different purposes. JAVA_HOME is for program configuration. PATH is for your convenience at the command line.

JAVA_HOME tells applications where the JDK is installed. Build tools like Maven and Gradle read JAVA_HOME and navigate to subdirectories as needed. They do not search PATH.

PATH tells the shell where to find executable commands. When you type java, the shell searches the directories in PATH to find the binary. The macOS built‑in Java launcher is available at /usr/bin/java, which is on the default PATH. You can override it by setting a $JAVA_HOME variable and adding $JAVA_HOME/bin to PATH to specify a different JDK executable.

Where to Set JAVA_HOME

You can set JAVA_HOME in either ~/.zprofile or ~/.zshrc. The article .zshrc or .zprofile explains the differences.

On macOS with the Zsh shell, a typical terminal window starts a login, interactive shell, which reads ~/.zprofile first (for login setup, with core environment variables like PATH) and then ~/.zshrc (for interactive tweaks like prompts, aliases, plugins). Putting JAVA_HOME in ~/.zprofile makes it part of your base login environment that all subsequent shells inherit, which is useful when you want every tool, script, and subshell to see the same JDK without extra work. Putting JAVA_HOME in ~/.zshrc makes it an interactive‑shell setting which is fine if you only care about terminal sessions, but less ideal if you keep PATH and other core variables in ~/.zprofile. For a clean setup, set both JAVA_HOME and any Java‑based PATH in ~/.zprofile, then use ~/.zshrc for shell behavior like aliases; that way, a new login gets a complete, consistent Java environment before any interactive configuration runs.

Find Your Java Installation

Before you can set JAVA_HOME, you must find the path to your installed JDK. Apple's macOS includes a built-in utility called java_home that locates installed JDKs. This tool handles the complexity of finding Java installations across different vendors and versions.

Get the Default JDK Path

Run the /usr/libexec/java_home command without arguments to get the path to your default (highest version) JDK. You must provide the command's full path:

$ /usr/libexec/java_home
/Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home

The utility returns the path to the Contents/Home directory, the JDK root that build tools expect. This output is what JAVA_HOME should contain.

If the JDK is Not Found

If the utility displays "Unable to locate a Java Runtime," no JDK is installed. If you installed Java using brew install --cask temurin or a .pkg installer from Oracle, Eclipse Adoptium, or Azul, the JDK should be installed to the standard Java location. See Download Java for Mac to install a JDK if you need it.

If you used a Homebrew formula to install Java, you may have overlooked setting the symlink. The macOS java_home utility cannot find JDKs installed in Homebrew directories automatically. Homebrew formula installations require a symlink to make the JDK discoverable. Read Brew Install Java - Formula Method for complete symlink instructions.

List All Installed JDKs

You can have more than one JDK installed on your Mac. If the default JDK is not what you want to use, you can check for the paths to other installed JDKs. Use the uppercase -V flag to see all installed JDKs with their architecture and vendor information:

$ /usr/libexec/java_home -V
Matching Java Virtual Machines (2):
    25.0.1 (arm64) "Eclipse Adoptium" - "OpenJDK 25.0.1" /Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home
    21.0.3 (arm64) "Eclipse Adoptium" - "OpenJDK 21.0.3" /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home

The output shows version numbers, CPU architecture (arm64 for Apple Silicon, x86_64 for Intel), vendor names, and full paths.

Select a Specific Version

Use the lowercase -v flag followed by a major version number to get the path for that version:

$ /usr/libexec/java_home -v 25
$ /usr/libexec/java_home -v 21
$ /usr/libexec/java_home -v 1.8

The last example uses Java 8's legacy versioning scheme. The utility matches the highest installed version that starts with your specified number.

Set JAVA_HOME Temporarily

You can set JAVA_HOME for your current terminal session without making permanent changes. This is useful for testing or troubleshooting.

Run this command:

$ export JAVA_HOME=$(/usr/libexec/java_home)

The setting lasts until you close the terminal window. New terminal sessions will not have this setting, so you should edit the ~/.zprofile to set JAVA_HOME permanently.

Understanding the Syntax

The command has three important parts:

  • export: Makes the variable available to programs you run from this shell. Without export, only the shell itself sees the variable. Maven and Gradle would not find it.
  • $(): Runs the enclosed command and captures its output. The shell executes /usr/libexec/java_home and substitutes the result.
  • No spaces around =: Shell syntax requires no spaces. Writing JAVA_HOME = ... (with spaces) causes an error.

Set a Specific Version Temporarily

To use a specific Java version for the current session:

$ export JAVA_HOME=$(/usr/libexec/java_home -v 25)

Replace 25 with your desired major version number, if you have multiple JDKs installed.

Set JAVA_HOME Permanently

For JAVA_HOME to persist across terminal sessions, add the export command to your shell configuration file. See the article Mac Shell Configuration for instructions about editing shell configuration files.

Add this line to your shell configuration for a Java 25 version:

export JAVA_HOME=$(/usr/libexec/java_home -v 25)

For this change to take effect, you'll either need to restart your terminal or reload your .zprofile file by entering source ~/.zprofile.

Set PATH to Match

The macOS Java system launcher will find the newest installed JDK to run Java. However, if you want to ensure consistency among command-line usage and build tool behavior, you can set both JAVA_HOME and PATH to use the same JDK. After setting JAVA_HOME in the .zprofile file, edit the .zprofile file again to set the Mac PATH for Java.

export JAVA_HOME=$(/usr/libexec/java_home -v 25)
export PATH="$JAVA_HOME/bin:$PATH"

This line adds the JDK's bin directory to your PATH, ensuring that java, javac, and other commands use your chosen JDK. You may know that you can set the PATH and JAVA_HOME in your .zshrc file but I recommend setting PATH in the .zprofile file. The article .zshrc or .zprofile explains the differences. For more details on PATH configuration, see Java PATH on Mac.

You only need JAVA_HOME set in the .zprofile file because .zprofile is loaded first for the initial login shell, then .zshrc runs afterward for interactive configuration. Developers often expect to find environment variables in the .zshrc so you might want to add a comment in the .zshrc documenting that you've set PATH and JAVA_HOME in your .zprofile file.

Why Both Lines Matter

  • JAVA_HOME is for build tools. Maven, Gradle, and Ant read this variable to find the JDK.
  • PATH is for the shell. When you type java or javac, the shell searches PATH to find the executable.

Setting both to the same JDK ensures consistency between command-line usage and build tool behavior.

Pin to a Specific Version

If you want JAVA_HOME to always point to a specific major version (regardless of other versions installed), specify the version:

export JAVA_HOME=$(/usr/libexec/java_home -v 25)

This ensures you always use Java 25, even if you install Java 26 later. If you want to use the latest installed Java version without specifying a version, use:

export JAVA_HOME=$(/usr/libexec/java_home)

Verify Your Configuration

After setting JAVA_HOME, confirm that everything works correctly.

Show the value of JAVA_HOME:

$ echo $JAVA_HOME
/Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home

You should see a path ending in Contents/Home. If the output is blank, JAVA_HOME is not set.

Confirm the Java Version

Run java -version to see which Java the shell uses:

$ java -version
openjdk version "25.0.1" 2025-10-21 LTS
OpenJDK Runtime Environment Temurin-25.0.1+12 (build 25.0.1+12-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.1+12 (build 25.0.1+12-LTS, mixed mode)

For more details on checking Java versions, see Check Java Version on Mac.

Verify the Path Resolves

Confirm that JAVA_HOME points to a valid JDK by running the Java binary directly:

$ $JAVA_HOME/bin/java -version

This should display the same version information. If it fails, JAVA_HOME points to an invalid path.

Shell Configuration Debugging

If your configuration is not loading:

# Add to ~/.zprofile to verify it loads
echo "DEBUG: zprofile loaded"

Open a new terminal. If you see the message, the file loads correctly. If not, check for syntax errors in the file or try adding your export to ~/.zprofile instead.

Verify Build Tools

If you have Maven installed, run:

$ mvn -version

The output includes a "Java home:" line showing which JDK Maven uses. This should match your JAVA_HOME.

Noet that you can configure build tools to use project-level Java configuration that does not depend on JAVA_HOME:

  • Gradle Toolchains auto-detect installed JDKs and can download required versions automatically
  • Maven Toolchains Plugin with ~/.m2/toolchains.xml specifies JDK versions per project

These approaches provide reproducible builds regardless of each developer's JAVA_HOME setting.

Manage Multiple Java Versions

Developers often work on projects requiring different Java versions. The java_home utility makes switching straightforward.

Change Versions in Current Session

To switch to a different version temporarily:

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

This affects only the current Terminal session.

Create Aliases for Quick Switching

Add these aliases to the ~/.zshrc file for convenient version switching:

alias j11='export JAVA_HOME=$(/usr/libexec/java_home -v 11); java -version'
alias j21='export JAVA_HOME=$(/usr/libexec/java_home -v 21); java -version'
alias j25='export JAVA_HOME=$(/usr/libexec/java_home -v 25); java -version'

By convention, aliases belong in the ~/.zshrc file. Restart your terminal or reload your .zshrc file by entering source ~/.zshrc to use the new aliases.

Version Managers

Version managers such as SDKMAN or jEnv handle JAVA_HOME automatically. They switch versions per-project using configuration files. If you use a version manager, avoid conflicts and do not set JAVA_HOME manually in the ~/.zprofile or ~/.zshrc files.

Read Java Version Managers to learn about automated version switching.

IDE-Specific Configuration

IntelliJ IDEA: Does not use system JAVA_HOME to run itself (it bundles JetBrains Runtime). Configure project SDK under File → Project Structure → Project. For Gradle projects, set the JVM under Settings → Build, Execution, Deployment → Gradle.

Eclipse: Manages Java through Window → Preferences → Java → Installed JREs. Configure the IDE runtime in eclipse.ini using the -vm flag.

VS Code with Java Extension Pack: Checks settings in this order: java.jdt.ls.java.home setting, JDK_HOME variable, JAVA_HOME variable, then PATH. Configure multiple runtimes in settings.json.

Android Studio: Checks STUDIO_JDK, then JDK_HOME, then JAVA_HOME on startup to find the JDK for Gradle builds.

Application Server Configuration

Apache Tomcat and similar servers expect JAVA_HOME or JRE_HOME to be set. The recommended approach is creating a setenv.sh script in CATALINA_BASE/bin/ to set these variables, keeping server configuration separate from your shell configuration.

Troubleshooting

Here are solutions to common JAVA_HOME problems.

"JAVA_HOME is not set"

Error messages:

  • "JAVA_HOME is not set"
  • "JAVA_HOME not defined"
  • "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH"

Causes and solutions:

  1. Missing export in config file. Check with grep JAVA_HOME ~/.zprofile. If nothing appears, add the export line.

  2. Wrong config file. Verify your shell with echo $SHELL. Use ~/.zprofile for zsh, ~/.bash_profile for bash.

  3. Config not loaded. Run source ~/.zprofile or open a new Terminal.

  4. Missing export keyword. The line must start with export. Without it, child processes (like Maven) cannot see the variable.

"JAVA_HOME is not defined correctly"

Error message (Maven): "The JAVA_HOME environment variable is not defined correctly. This environment variable is needed to run this program. NB: JAVA_HOME should point to a JDK not a JRE."

Causes and solutions:

  1. Pointing to bin directory. JAVA_HOME should end with Contents/Home, not Contents/Home/bin. Check with echo $JAVA_HOME.

  2. Pointing to a JRE. Verify you have a JDK: ls "$JAVA_HOME/bin/javac". If javac is missing, install a full JDK.

  3. Path does not exist. Verify the path: ls -la $JAVA_HOME. If it fails, the JDK was moved or uninstalled.

"Unable to locate a Java Runtime"

This message comes from the /usr/libexec/java_home utility when it cannot find any JDK.

Causes and solutions:

  1. No JDK installed. Install a JDK using Homebrew or a vendor installer. See Download Java for Mac.

  2. Homebrew JDK not linked. Run the symlink command from brew info openjdk. See Brew Install Java - Formula Method.

  3. JDK in non-standard location. Move it to /Library/Java/JavaVirtualMachines/ or set JAVA_HOME directly to the path.

Wrong Java Version Being Used

Symptoms: java -version shows a different version than expected, or builds use the wrong version.

Causes and solutions:

  1. Multiple JAVA_HOME exports. Check your config file for duplicate lines. Only the last one takes effect.

  2. PATH pointing elsewhere. Run which java to see which binary the shell finds. It should be $JAVA_HOME/bin/java.

  3. Version manager conflict. If you use SDKMAN or jEnv, let it control JAVA_HOME. Remove manual exports from ~/.zprofile.

  4. IDE using different JDK. IDEs have their own SDK settings. Check your IDE's project configuration.

Settings Disappear After Restart

Cause: You set JAVA_HOME in the Terminal directly, not in a configuration file.

Solution: Add the export line to ~/.zprofile as described in "Set JAVA_HOME Permanently."

JAVA_HOME Works in Terminal but Not in IDE

Cause: GUI applications launched from Finder or Spotlight do not inherit Terminal environment variables.

Solutions:

  1. Configure Java in the IDE. Most IDEs (IntelliJ, Eclipse, VS Code) have their own Java/SDK settings. This is the recommended approach.

  2. Use launchctl (advanced). For edge cases:

$ launchctl setenv JAVA_HOME "$(/usr/libexec/java_home)"

This sets JAVA_HOME for GUI applications until you log out.

Intel Mac Differences

The concepts are identical on Intel Macs. Only paths differ:

  • Homebrew cellar: /usr/local/opt/openjdk (instead of /opt/homebrew/opt/openjdk)
  • The symlink destination remains /Library/Java/JavaVirtualMachines/
  • The java_home utility works identically

Verification Commands

Use these commands to diagnose problems:

$ echo $JAVA_HOME                    # Current JAVA_HOME value
$ echo $SHELL                        # Which shell you use
$ /usr/libexec/java_home -V          # All installed JDKs
$ which java                         # Which java binary PATH finds
$ ls -la $JAVA_HOME                  # Verify path exists
$ ls "$JAVA_HOME/bin/javac"          # Verify it's a JDK
$ grep JAVA_HOME ~/.zprofile            # Check config file

Best Practices

Follow these recommendations for a reliable JAVA_HOME setup.

Use the java_home utility. Apple provides this tool specifically for locating JDKs. It handles version discovery and abstracts away installation paths.

Prefer dynamic assignment. Using $(/usr/libexec/java_home) instead of a hardcoded path means your configuration survives Java updates. Minor version upgrades will not break your setup.

Avoid hardcoded paths. A hardcoded path like /Library/Java/JavaVirtualMachines/temurin-25.jdk/Contents/Home ties you to one specific installation. It requires manual updates and does not port well to other machines.

Set both JAVA_HOME and PATH. The complete configuration ensures consistency:

# in .zprofile
export JAVA_HOME=$(/usr/libexec/java_home)
export PATH="$JAVA_HOME/bin:$PATH"

Document your setup. For team projects, include JAVA_HOME configuration steps in your README. Specify the required JDK version and installation method.

Choose one version management approach. Either configure JAVA_HOME manually (as shown in this guide) or use a version manager like SDKMAN. Do not mix approaches.

What's Next

With JAVA_HOME configured, your Mac is ready for Java development. Consider these next steps:

  • Install Maven or Gradle for project builds
  • Set up an IDE like IntelliJ IDEA, Eclipse, or VS Code with Java extensions
  • Create your first project to verify everything works end-to-end

My mac.install.guide is a trusted source of installation guides for professional developers. Take a look at the Mac Install Guide home page for tips and trends and see what to install next.