194

I need to work around a Java bug in JDK 1.5 which was fixed in 1.6. I'm using the following condition:

if (System.getProperty("java.version").startsWith("1.5.")) {
    ...
} else {
    ...
}

Will this work for other JVMs? Is there a better way to check this?

0

15 Answers 15

175

java.version is a system property that exists in every JVM. There are two possible formats for it:

  • Java 8 or lower: 1.6.0_23, 1.7.0, 1.7.0_80, 1.8.0_211
  • Java 9 or higher: 9.0.1, 11.0.4, 12, 12.0.1

Here is a trick to extract the major version: If it is a 1.x.y_z version string, extract the character at index 2 of the string. If it is a x.y.z version string, cut the string to its first dot character, if one exists.

private static int getVersion() {
    String version = System.getProperty("java.version");
    if(version.startsWith("1.")) {
        version = version.substring(2, 3);
    } else {
        int dot = version.indexOf(".");
        if(dot != -1) { version = version.substring(0, dot); }
    } return Integer.parseInt(version);
}

Now you can check the version much more comfortably:

if(getVersion() < 6) {
    // ...
}
Sign up to request clarification or add additional context in comments.

10 Comments

It is ok for 1.5 but 1.6 is not precise as a floating point number.
FP precision aside, for the OP's needs the code provided should at least be (version > 1.5), not >=. To the OP: if you use your current String comparison do you need to check below 1.5 too?
@Ha: Maybe but double version = 1.6 and Double.parseDouble("1.6") should still yield the same bit pattern, right? Since we don't do arithmetics on the number (only a simple compare), even == will work as expected.
but soon we will have version 1.1 again... or maybe instead of 1.10 we start with 2.0 [:-)
In Java 9, there won't be "1." in front. The string will start with "9..."
|
75

Runtime.version()

Since Java 9, you can use Runtime.version(), which returns a Runtime.Version:

Runtime.Version version = Runtime.version();

4 Comments

echo "System.err.print(Runtime.version().major())" | $JDK/bin/jshell 2>&1 > /dev/null
@judovana Runtime.version().major() is deprecated since Java10, the equivalent is now Runtime.version().feature().
yes it doesnt works now
Detail: not available in Java 8 or earlier - question was about testing for Java 1.5
64

What about getting the version from the package meta infos:

String version = Runtime.class.getPackage().getImplementationVersion();

Prints out something like:

1.7.0_13

3 Comments

Wow, that kind of blew my mind. Though in my case, all I wanted was the first two parts of the version so: Runtime.class.getPackage().getSpecificationVersion()
Runtime.class.getPackage().getImplementationVersion() seems to return null on JDK9.
Maybe this only works when it's defined in MANIFEST.MF?
44

These articles seem to suggest that checking for 1.5 or 1.6 prefix should work, as it follows proper version naming convention.

Sun Technical Articles

3 Comments

Is there a way to obtain whether it's Oracle or Open?
Now that the versioning syntax has changed beginning in Java 9, the other answers are more useful.
To address @JoeC question some years later: look at some of the other system properties, in particular these six: java.runtime.name, java.vendor, java.vm.{name,vendor}, java.vm.specification.{name,vendor} I believe the first two may be semi-standardized by the official JVM/JLS spec, and the rest may be sort of standard conventions by now. Depending on what exactly the use case is in the application, often one or more of those properties can be the deciding factor.
34

The simplest way (java.specification.version):

double version = Double.parseDouble(System.getProperty("java.specification.version"));

if (version == 1.5) {
    // 1.5 specific code
} else {
    // ...
}

or something like (java.version):

String[] javaVersionElements = System.getProperty("java.version").split("\\.");

int major = Integer.parseInt(javaVersionElements[1]);

if (major == 5) {
    // 1.5 specific code
} else {
    // ...
}

or if you want to break it all up (java.runtime.version):

String discard, major, minor, update, build;

String[] javaVersionElements = System.getProperty("java.runtime.version").split("\\.|_|-b");

discard = javaVersionElements[0];
major   = javaVersionElements[1];
minor   = javaVersionElements[2];
update  = javaVersionElements[3];
build   = javaVersionElements[4];

1 Comment

your version with java.runtime.version is broken for Java 9 (java.lang.ArrayIndexOutOfBoundsException).
14

Example for Apache Commons Lang:

import org.apache.commons.lang.SystemUtils;

    Float version = SystemUtils.JAVA_VERSION_FLOAT;

    if (version < 1.4f) { 
        // legacy
    } else if (SystemUtils.IS_JAVA_1_5) {
        // 1.5 specific code
    } else if (SystemUtils.isJavaVersionAtLeast(1.6f)) {
        // 1.6 compatible code
    } else {
        // dodgy clause to catch 1.4 :)
    }

6 Comments

version < 1.4f... What happens when version = 1.4f?
Ah yes, you are right - 1.4f would not be captured in the above example. The example is only demonstrating Apache Commons Lang's constants as an alternative to Java's properties :)
You can edit the answer and change it to version <= 1.4f.. Unfortunately SystemUtils does not provide a isJavaVersionLessThan method but then (fortunately) you could also put the legacy code in an else block, which is cleaner.
Err... "dodgy clause to catch 1.4"? Shouldn't 1.4f fall back to legacy code?
I would suggest: if (SystemUtils.IS_JAVA_1_5) { /* 1.5 specific code */ } else if (SystemUtils.isJavaVersionAtLeast(1.6f)) { /* modern code */ } else { /* fall back to legacy code */ }. Specific code above, generic code below, fallback code at the very bottom.
|
12

Just a note that in Java 9 and above, the naming convention is different. System.getProperty("java.version") returns "9" rather than "1.9".

1 Comment

from after java 1.8, it's no longer 1.x? continues with 9, 10...?
8

Does not work, need --pos to evaluate double:

    String version = System.getProperty("java.version");
    System.out.println("version:" + version);
    int pos = 0, count = 0;
    for (; pos < version.length() && count < 2; pos++) {
        if (version.charAt(pos) == '.') {
            count++;
        }
    }

    --pos; //EVALUATE double

    double dversion = Double.parseDouble(version.substring(0, pos));
    System.out.println("dversion:" + dversion);
    return dversion;
}

Comments

8

Here's the implementation in JOSM:

/**
 * Returns the Java version as an int value.
 * @return the Java version as an int value (8, 9, etc.)
 * @since 12130
 */
public static int getJavaVersion() {
    String version = System.getProperty("java.version");
    if (version.startsWith("1.")) {
        version = version.substring(2);
    }
    // Allow these formats:
    // 1.8.0_72-ea
    // 9-ea
    // 9
    // 9.0.1
    int dotPos = version.indexOf('.');
    int dashPos = version.indexOf('-');
    return Integer.parseInt(version.substring(0,
            dotPos > -1 ? dotPos : dashPos > -1 ? dashPos : 1));
}

1 Comment

6

If you can have dependency to apache utils you can use org.apache.commons.lang3.SystemUtils.

    System.out.println("Is Java version at least 1.8: " + SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));

Comments

3

Don't know another way of checking this, but this: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#getProperties()" implies "java.version" is a standard system property so I'd expect it to work with other JVMs.

Comments

1

Here is the answer from @mvanle, converted to Scala: scala> val Array(javaVerPrefix, javaVerMajor, javaVerMinor, _, _) = System.getProperty("java.runtime.version").split("\\.|_|-b") javaVerPrefix: String = 1 javaVerMajor: String = 8 javaVerMinor: String = 0

Comments

0

https://docs.oracle.com/javase/9/docs/api/java/lang/Runtime.Version.html#version--

 Runtime.version().version()

For 17.0.1 it returns [17, 0, 1] One can use Runtime.version().version().get(0) to get the major java version.

1 Comment

Detail: not available in Java 8 or earlier - question is about testing for Java 1.5
0

Since Java 10, use:

int required = 21;
int feature = Runtime.version().feature();
if (feature < required) {
    throw new IllegalStateException(String.format("Java version is %d, required %d", feature, required));
}

Runtime.version().major() is deprecated

Stolen from a comment by @fidekild

1 Comment

please bake all of your relevant insights into your answer via an edit then delete your comments. Anything that is not relevant can be simply deleted (and should be, by you, to keep the Q&A clean).
-1

In kotlin:

/**
 * Returns the major JVM version, e.g. 6 for Java 1.6, 8 for Java 8, 11 for Java 11 etc.
 */
public val jvmVersion: Int get() = System.getProperty("java.version").parseJvmVersion()

/**
 * Returns the major JVM version, 1 for 1.1, 2 for 1.2, 3 for 1.3, 4 for 1.4, 5
 * for 1.5 etc.
 */
fun String.parseJvmVersion(): Int {
    val version: String = removePrefix("1.").takeWhile { it.isDigit() }
    return version.toInt()
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.