In 2024, even if you can use just brew..
Copybrew install openjdk@17
Java will be installed here:
Copy/opt/homebrew/opt/openjdk@17/bin/java
for Apple Intel path is /usr/local/... rather than /opt/homebrew/...
For the system Java wrappers to find this JDK, symlink it with:
Copysudo ln -sfn /opt/homebrew/opt/openjdk\@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
resp. for Intel
Copysudo ln -sfn /usr/local/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
Now, running /usr/libexec/java_home -V should show the path to JAVA 17, something like:
Copy17.0.9 (x86_64) "Homebrew" - "OpenJDK 17.0.9" /opt/homebrew/Cellar/openjdk@17/17.0.9/libexec/openjdk.jdk/Contents/Home
(This is what you are missing btw, if javac or javac --version does not give you a command-not-found but an The operation couldn’t be completed. Unable to locate a Java Runtime.)
In case you see the wrong version, check if the path to JAVA_HOME is set correctly. If not, you could set it by:
Copyexport JAVA_HOME=\$(/usr/libexec/java_home)
...give a try to sdkman, it's far better than brew
Copycurl -s "https://get.sdkman.io" | bash
then open a new shell and try list to see what you could install ;-)
Copysdk list java
At time of writing you could use:
Copysdk install java 17.0.4.1-tem
Java will be installed here:
Copy/Users/YOUR_USERNAME_HERE/.sdkman/candidates/java/17.0.4.1-tem
Answer from freedev on Stack OverflowIn 2024, even if you can use just brew..
Copybrew install openjdk@17
Java will be installed here:
Copy/opt/homebrew/opt/openjdk@17/bin/java
for Apple Intel path is /usr/local/... rather than /opt/homebrew/...
For the system Java wrappers to find this JDK, symlink it with:
Copysudo ln -sfn /opt/homebrew/opt/openjdk\@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
resp. for Intel
Copysudo ln -sfn /usr/local/opt/openjdk@17/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk
Now, running /usr/libexec/java_home -V should show the path to JAVA 17, something like:
Copy17.0.9 (x86_64) "Homebrew" - "OpenJDK 17.0.9" /opt/homebrew/Cellar/openjdk@17/17.0.9/libexec/openjdk.jdk/Contents/Home
(This is what you are missing btw, if javac or javac --version does not give you a command-not-found but an The operation couldn’t be completed. Unable to locate a Java Runtime.)
In case you see the wrong version, check if the path to JAVA_HOME is set correctly. If not, you could set it by:
Copyexport JAVA_HOME=\$(/usr/libexec/java_home)
...give a try to sdkman, it's far better than brew
Copycurl -s "https://get.sdkman.io" | bash
then open a new shell and try list to see what you could install ;-)
Copysdk list java
At time of writing you could use:
Copysdk install java 17.0.4.1-tem
Java will be installed here:
Copy/Users/YOUR_USERNAME_HERE/.sdkman/candidates/java/17.0.4.1-tem
Java doesn't mind if you install multiple versions. This is often required; java is not backwards compatible (it tries to change little, but e.g. the java8 to java9 transition broke a ton of stuff, much of it needless and much of it not reasonably expectable or fixable by libraries and apps, so a bunch of java apps and libraries only run on java8 - just an example).
So, yes, you have installed JDK17. Also, yes, if you just run java without specifying which one you want, you so happen to get java13 here.
To see all installed javas, you can run:
Copy/usr/libexec/java_home -V
to 'override', you can use something like (depends on which shell you're using on your mac):
Copyexport JAVA_HOME=`/usr/libexec/java_home -v 17`
(the backticks mean: Run this then take the output of it and treat that as the 'value' of the expression. here, assign it to the JAVA_HOME env var. -v 17 requests a path to java 17. The -V option lists all and is meant for your eyeballs, not for scripts. The -v option is mostly for scripting, and that's how we're using it here).
JAVA_HOME decides which java is used by some things, but the java you get when you just type java is /usr/bin/java, and that executable is actually just a wrapper that picks a java to run from amongst all installed versions. It uses JAVA_HOME to decide which java to actually run. There are wrappers for all the common commands (javac, too). You can always run e.g. which javac to see what that actually runs; you probably see /usr/bin/javac. Everything in /usr/bin is one of these wrapper thingies that looks at JAVA_HOME and then runs the binary it finds there.
How to set or change the default Java (JDK) version on macOS? - Stack Overflow
How to update my Java from 17 to 22?
How to install Java?
How do I change the default version of Java that Curse uses to launch Minecraft?
Videos
First run /usr/libexec/java_home -V which will output something like the following:
Matching Java Virtual Machines (3):
1.8.0_05, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home
1.6.0_65-b14-462, x86_64: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
1.6.0_65-b14-462, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
/Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home
Pick the version you want to be the default (1.6.0_65-b14-462 for arguments sake) then:
export JAVA_HOME=`/usr/libexec/java_home -v 1.6.0_65-b14-462`
or you can specify just the major version, like:
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
Now when you run java -version you will see:
java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)
Add the export JAVA_HOME… line to your shell’s init file.
For Bash (as stated by antonyh):
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)
For Fish (as stated by ormurin)
set -x JAVA_HOME (/usr/libexec/java_home -d64 -v1.8)
Updating the .zshrc file should work:
nano ~/.zshrc
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8.0)
Press CTRL+X to exit the editor Press Y to save your changes
source ~/.zshrc
echo $JAVA_HOME
java -version
This answer is an attempt to address: how to control java version system-wide (not just in currently running shell) when several versions of JDK are installed for development purposes on macOS El Capitan or newer (Sierra, High Sierra, Mojave). As far as I can tell, none of the current answers do that (*).
As a developer, I use several JDKs, and I want to switch from one to the other easily. Usually I have the latest stable one for general use, and others for tests. But I don't want the system (e.g. when I start my IDE) to use the latest "early access" version I have for now. I want to control system's default, and that should be latest stable.
The following approach works with Java 7 to 12 at least (early access at the time of this writing), with Oracle JDK or OpenJDK (including builds by AdoptOpenJDK produced after mid-October 2018).
Solution without 3rd party tools:
- leave all JDKs at their default location, under
/Library/Java/JavaVirtualMachines. The system will pick the highest version by default. - To exclude a JDK from being picked by default, rename its
Contents/Info.plisttoInfo.plist.disabled. That JDK can still be used when$JAVA_HOMEpoints to it, or explicitly referenced in a script or configuration. It will simply be ignored by system'sjavacommand.
System launcher will use the JDK with highest version among those that have an Info.plist file.
When working in a shell with alternate JDK, pick your method among existing answers (jenv, or custom aliases/scripts around /usr/libexec/java_home, etc).
Details of investigation in this gist.
(*) Current answers are either obsolete (no longer valid for macOS El Capitan or Sierra), or only address a single JDK, or do not address the system-wide aspect. Many explain how to change $JAVA_HOME, but this only affects the current shell and what is launched from there. It won't affect an application started from OS launcher (unless you change the right file and logout/login, which is tedious). Same for jenv, it's cool and all, but as far as I can tell it merely changes environment variables, so it has the same limitation.