I have a Java desktop application which is supposed to run in both GNU Linux distributions (Debian and Ubuntu) and MUSL Linux distributions (Alpine). My application uses a native library also and native library build is different for both type of Linux distributions.
I will deliver both with my application in different folders. So at runtime Java program needs to pick the right distribution of native library to pick as per Linux (GNU or MUSL).
I don’t find any mechanism to know that in the Java program, which Linux distribution JVM is running on.
One way I was thinking to read the OS file from /etc/ folder of Linux. But I don’t think it would be a good solution (as some custom build might change this details), can someone suggest some better solution for this problem? Or how this can be done?
2
Answers
You can detect which Linux Distribution is running by following this StackOverflow answer
Unfortunately there aren’t so many alternatives to detect if you are running on MUSL or GLIBC
Using Java/JNA, you can map the
gnu_get_libc_version()
function and attempt to execute it after loadinglibc
. If it works, you’re on glibc (GNU). If you get anUnsatisfiedLinkError
that the function is not found, you’re on some other libc.Map the function:
Call it:
There may be similar approaches with a unique function to distinguish other libc variants from MUSL, but as far as I’m aware, MUSL attempts to be so standards-compliant that it doesn’t really allow identifying itself.
Another option for finding GNU distributions is the
uname -o
command that you can execute with a ProcessBuilder.On non-GNU (Alpine) it is just "Linux" while on Ubuntu, Debian and OpenSUSE it is "GNU/Linux".
You may also have success determining GNU vs. MUSL by iterating
/lib*
directories looking for libc variants. This is similar to the approach taken when compiling the JDK, which executes theldd
command and parses libraries from that output.For example, iterating the
/lib
directory in Alpine linux gives this link:libc.musl-x86_64.so.1 -> ld-musl-x86_64.so.1
In Debian
/lib32
haslibc.so.6 -> libc-2.28.so
, and in OpenSUSE/lib64
I see something similar:libc.so.6 -> libc-2.26.so
, and Ubuntu/lib/aarch64-linux-gnu
haslibc-2.27.so
.If you stay within Java, determining which
/lib
path to search may require some trial-and-error. Parsing the output of a command line such asldd `which ls`
will likely get you a string containinggnu
ormusl
.As far as determining which Linux Distribution to use, reading from an
/etc
folder is a good intuition. I manage the Java-based Operating System and Hardware Information (OSHI) project, and went through pretty much all the options to identify which distribution you are running. You can see the results of all that labor in this class.I’ll quote a comment in that file:
The code’s logic goes:
/etc/system-release
/etc/os-release
lsb_release
command/etc/lsb-release
/etc/*-release
file.Those files contain keys like
NAME
that help you out.Feel free to copy and use that file or a variant, or just use that project as a dependency.