4

I'm trying to infer the Java versions of installed JDKs/JREs. I see a lot of code out there that runs java -version and parses the output, but that is a bit expensive and annoying to write. Besides, the output of java -version doesn't include important information like the OS and architecture (especially important nowadays with M1 Macs that can support multiple architectures).

I notice that in all the JDKs that I have installed, there is a release file with the line JAVA_VERSION="<VERSION>".

For example, Amazon Corretto 8 has a release file that says

cat release
JAVA_VERSION="1.8.0_322"
OS_NAME="Windows"
OS_VERSION="5.1"
OS_ARCH="i586"
SOURCE=""
LIBC=""

And Zulu 17 says

IMPLEMENTOR="Azul Systems, Inc."
IMPLEMENTOR_VERSION="Zulu17.32+13-CA"
JAVA_VERSION="17.0.2"
JAVA_VERSION_DATE="2022-01-18"
LIBC="default"
MODULES="java.base java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.logging java.management java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.compiler jdk.crypto.ec jdk.crypto.cryptoki jdk.dynalink jdk.internal.ed jdk.editpad jdk.hotspot.agent jdk.httpserver jdk.incubator.foreign jdk.incubator.vector jdk.internal.le jdk.internal.opt jdk.internal.vm.ci jdk.internal.vm.compiler jdk.internal.vm.compiler.management jdk.jartool jdk.javadoc jdk.jcmd jdk.management jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported jdk.unsupported.desktop jdk.xml.dom jdk.zipfs"
OS_ARCH="x86_64"
OS_NAME="Darwin"
SOURCE=".:git:bfa6b2cbcbf7"

I'm unable to find a JEP or any other documentation that says this file will always be there, but also unable to find a counterexample. (I'm also not able to find a JEP or documentation about the format of the output of `java -version)

Is it safe to assume that there will always be a release file with at least a JAVA_VERSION line?

Marquis Wang
  • 10,878
  • 5
  • 30
  • 25
  • What makes you say that capturing the result of asking the actual java/javac executable for its version number "a bit expensive and annoying to write", given that that's the only true way to know which version is going to be running? Surely getting the correct information every single time is worth the one-time hassle of writing the code that captures that? – Mike 'Pomax' Kamermans Apr 18 '22 at 22:49
  • 1
    @Mike'Pomax'Kamermans That's a good question. I have other complaints about the output of `java -version`. It isn't in an easily parseable format. The format is similarly undocumented (to my knowledge), and could change. It doesn't include the OS or architecture. So in many ways the `release` file is superior, assuming it is consistent. – Marquis Wang Apr 18 '22 at 23:15
  • If it is not officially documented that the file exists, it is not **safe** to assume that it exists. – Stephen C Apr 18 '22 at 23:27
  • @StephenC I'm not certain that it *isn't* officially documented somewhere. Similarly, I don't see any documentation about the output of `java -version` either. – Marquis Wang Apr 18 '22 at 23:32
  • Instead of relying on the OS level files or commands why not the java internal properties? https://stackoverflow.com/a/68555328/460557 – Jorge Campos Apr 18 '22 at 23:38
  • those properties are documented https://docs.oracle.com/javase/7/docs/api/java/lang/System.html (first google link i found) – Jorge Campos Apr 18 '22 at 23:41

4 Answers4

3

Can I assume that a JDK/JRE will have a "release" file?

You can assume anything that you like. We can't stop you :-)

However ...

If it is not officially publicly documented that the "release" file exists, it is not safe to assume that it exists. And I don't recall seeing any documentation that mentions the "release" file.

(Documentation in the OpenJDK source tree / build instructions does not count. That is "internal", and subject to change without notice.)

This is not to say that the file is not present in all Java releases ... or that it is likely to change in the future. But safe implies that you can rely on it. If it ain't documented, you can't rely on it.

By contrast, while the output of java -version is also not specified, the option is at least documented. And typical output is at least shown on the Oracle website:

Determining the Default Version of the JDK on Mac

When launching a Java application through the command line, the system uses the default JDK. It is possible for the version of the JRE to be different than the version of the JDK.

You can determine which version of the JDK is the default by typing java -version in a Terminal window. If the installed version is 7u55, you will see a string that includes the text 1.7.0_55. For example:

java -version
java version "1.7.0_55"
Java(TM) SE Runtime Environment (build 1.7.0_55-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.55-b03, mixed mode)

Source: https://www.java.com/en/download/help/version_manual.html


"What is the safest way to detect Java version, Distributor, OS, and Architecture given a JDK"?

That is a matter of opinion ... but my opinion is that you should write a tiny utility that reads the information from the system properties object ... using (only) the properties that are explicitly documented in the javadoc.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • 2
    I should have phrased this question differently, as "What is the safest way to detect Java version, Distributor, OS, and Architecture given a JDK"? – Marquis Wang Apr 18 '22 at 23:34
0

I also don't like parsing the output of java -version - it would be great if java provide more machine readable output of this information (for example java -lookup-property java.version).

A problem with relying on the release file is now your bootstrapping logic may now be responsible for traversing symlinks to figure out where the java home / release file is (if you are relying on java from the system PATH).

I've created a simple library expressly for the purpose of getting property information out (java.version, java.home, etc) the "correct" way:

java -cp utilities.jar LookupProperty <property.name>

or

from java_utilities import lookup_property
print(lookup_property("java.version"))

https://github.com/devinrsmith/java-utilities

0

Try: java -XshowSettings:properties

STB
  • 11
  • 1
0

Something like this should work:

public static void main(String[] args) {
    System.out.println(System.getProperty("java.runtime.name"));
    System.out.println(System.getProperty("java.runtime.version"));
    System.out.println(System.getProperty("java.version.date"));
    System.out.println(System.getProperty("java.specification.vendor"));
    System.out.println(System.getProperty("os.name"));
}

To list all the properties run java -XshowSettings look at section Property settings or in plain java:

Properties properties = System.getProperties();
// Java 8
properties.forEach((k, v) -> System.out.println(k + "=" + v));
sedrakpc
  • 508
  • 4
  • 18