Why is my JDK not found on MacOS?
Whether you're working on a Kotlin Multiplatform project in XCode or trying to use VisualVM to debug a running JVM process, you may have run into an issue where your installed JDK is simply not found. It really depends on whether or not you've opted to install the JDK via OS package manager or userland.
For starters, lets run the java_home
tool that comes with MacOS on a brand new machine and see what its output is.
$ /usr/libexec/java_home -V
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
That's going to be our baseline. Obviously since we haven't even installed any JDK yet, this makes sense to see. Let's try out some various ways to install the JDK and see what is different.
SDKMAN
The instructions for SDKMAN are pretty straightforward, but I'm going to walk through the steps anyway just to be thorough:
brew tap sdkman/tap
brew install sdkman-cli
SDKMAN's script mentions running the following to ensure your profile is getting the current version of any tools you've configured with it:
vim .zprofile
# add the following
export SDKMAN_DIR=$(brew --prefix sdkman-cli)/libexec
[[ -s "${SDKMAN_DIR}/bin/sdkman-init.sh" ]] && source "${SDKMAN_DIR}/bin/sdkman-init.sh"
Now we can install whichever JDK we want to try out:
# Continue installing JDK 21
source .zprofile
sdk install java 22.0.2-zulu
In the same shell I'm able to see that JAVA_HOME environment variable is set
➜ ~ echo $JAVA_HOME
/opt/homebrew/opt/sdkman-cli/libexec/candidates/java/22.0.2-zulu
However if we look at the java_home
tool again:
$ /usr/libexec/java_home -V
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
So out of the box this doesn't work. And the SDKMAN FAQ page specifically calls out this behavior.
The java_home
tool is a system-level tool provided by OSX. On the other hand, SDKMAN is a userspace tool that operates on your home folder only. These tools are mutually exclusive and can't be used together
Challenge accepted.
Oracle Installer PKG
If you have chosen to grab the JDK via Oracle's downloads and run the Installer package, you'll find that it mentions installing the JDK for all users and prompts for your login password to be able to do this.
Interestingly this method results in the correct behavior from the OS tool java_home
:
$ /usr/libexec/java_home -V
Matching Java Virtual Machines (1):
23.0.1 (arm64) "Oracle Corporation" - "Java SE 23.0.1" /Library/Java/JavaVirtualMachines/jdk-23.jdk/Contents/Home
So what is different between this installer package and SDKMAN?
Finding libexec/java_home requirements
That StackOverflow post describes most of what is needed. While the instructions provided work well enough for some Java apps that use libexec, others like Eclipse MemoryAnalyzer require a proper symlink to Contents/MacOS/libjli.dylib
.
asdf
Another CLI tool that can manage multiple language runtime versions allows for managing JDK versions. Upon reading its Java plugin documentation there is a configuration setting that automatically writes the expected MacOS libexec/java_home
requirements. While it is an opt-in setting, it is fairly straightforward to use.
Automating linking userspace JDK installs
I wrote a GitHub repository that has scripts for asdf
, SDKMAN
, and homebrew
with supporting CI checks that verify libexec/java_home
can view their respective JDK installs. Generally I'd recommend using homebrew
for JDK installation if you don't already have a preference since homebrew
is the only tool among these which will automatically update when there are patch releases.