Working with different projects, each one having different JDK version requirements (mainly 1.8 and 17), with people contributing from different operating systems; it has been decided to use the JAVA_HOME
environment variable within our gradle
scripts to get the JDK path.
It works well, though one needs to export JAVA_HOME
to a different value, that differs for each individual contributor, each time one switches to another project.
I searched here at Stack sites, the SdkMan project and this blog post https://opensource.com/article/22/3/find-java-home about this topic.
The proposed solutions introduces much complexity to determine system type, locate available JDKs.
I ended-up writing my own implementation to find the JAVA_HOME
of a specific JDK version, although it only supports RedHat and Debian based Linux distributions.
Is there a standard method to determine the JAVA_HOME
, for a specific JDK version, in a fully system-agnostic way; be it Linux, BSD/MacOS, Windows?
Here is the shell script I wrote, only for Debian/RedHat based systems.
java_home
:
#!/bin/sh
# Usage:
# java_home [JDK_VERSION]
get_home() {
# get java_home from javac path
printf %s\\n "${1%/bin/javac}"
}
query_javac() {
{
command "$__ALTERNATIVES" --query javac || return 1
} | awk -v t="$1" \
'BEGIN{p="^" toupper( substr( t, 1, 1 ) ) substr( t, 2 ) ":"}$0~p{print $2}'
}
# find the alternatives command for this system
for cmd in update-alternatives alternatives false; do
__ALTERNATIVES=$(command -v "$cmd") && break
done
# If no version provided, return the home of the Best java version
java_home=$(
if [ $# -eq 0 ]; then
get_home "$(query_javac best)"
else
# Iterate the Alternative java versions
query_javac alternative |
while read -r javac; do
# Read the version string returned by the javac command
raw_javac_version=$(command "$javac" -version 2>&1)
case $raw_javac_version in
javac\ $1*)
# Print the home of this javac version and exit
get_home "$javac"
exit
;;
esac
done
fi
)
if [ -n "$java_home" ]; then
printf %s\\n "$java_home"
else
exit 1
fi
Example usage:
$ java_home 1.8
/usr/lib/jvm/java-8-openjdk-amd64
I am seeking a lighter, more standard, and more agnostic method of determining the Java home of specific JDK version.
CodePudding user response:
Is there a standard method to determine the JAVA_HOME, for a specific JDK version, in a fully system-agnostic way; be it Linux, BSD/MacOS, Windows?
As @Olivier noted, on Windows you can install a JDK anywhere. The same is true on Linux, and probably on MacOS too.
So given that the JDK could be installed anywhere, it will be impractical to try to find it. A truly system agnostic solution is impossible.
For example, your current approach will fail if javac
is not on the command searchpath (i.e. $PATH
), or if the user has installed a JRE rather than a JDK.
Is this really a problem?
Only if you call it a problem!
The pragmatic solution is:
Use a platform specific approach to finding the JDK; for example:
- On Windows, use the registry to find the JDK
- On Linux, use the
alternatives
mechanism and/or the default installation locations used by the distro's package manager or the OpenJDK RPMs. - On MacOS look in /Library/Java/JavaVirtualMachines. Or use the
java_home
tool.
If your best efforts don't find the JDK, throw the problem back to the person installing the application that needs a JDK or JRE:
- Recommend a preferred way to install Java
- Tell the user how to set up the environment variables by hand.
Or you could just make installing sdkman
a prerequisite for your projects. (Except that sdkman
is not in (for example) the Ubuntu or RedHat package repositories, and it probably won't play nice with the package manager's update mechanism.)
Note: deciding to call it a problem won't actually get you a solution. As I said, there is no system agnostic solution that will work in all circumstances. This is just a "wicked problem".