Why is my JDK not found on MacOS?

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

How to make /usr/libexec/java_home find JDK installed using SDKMAN on MacOS?
I am making iOS apps in Kotlin, which relies on having a Script Build Phase calling Gradle from XCode. With a JDK installed using SDKMAN, it does not work and produces this error: The operation cou…

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.