在运行时获取Java版本

181

我需要解决JDK 1.5中的Java bug,该问题在1.6中已经修复。我使用以下条件:

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

这对其他JVM是否适用?有更好的检查方法吗?

14个回答

160

java.version 是每个JVM中都存在的系统属性。它有两种可能的格式:

  • Java 8或更低版本:1.6.0_231.7.01.7.0_801.8.0_211
  • Java 9或更高版本:9.0.111.0.41212.0.1

这里有一个技巧可以提取主要版本号:如果是 1.x.y_z 版本字符串,则提取字符串索引2处的字符。如果是 x.y.z 版本字符串,则将字符串裁剪到其第一个点字符(如果存在)。

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);
}

现在你可以更加方便地检查版本:

if(getVersion() < 6) {
    // ...
}

8
1.5是可以的,但1.6作为浮点数不够精确。 - Ha.
1
除了FP精度之外,对于OP的需求,提供的代码至少应该是(版本>1.5),而不是>=。针对OP:如果您使用当前的字符串比较,您是否需要检查低于1.5的版本? - Steven Mackenzie
1
@Ha:也许吧,但是double version = 1.6Double.parseDouble("1.6")仍然应该产生相同的位模式,对吗?由于我们不对数字进行算术运算(只是简单比较),所以即使是==也能正常工作。 - Aaron Digulla
1
但很快我们将再次拥有1.1版本...或者也许我们可以跳过1.10,直接开始2.0版本 [:-) - user85421
10
Java 9 中,前面将不再有“1.”,字符串将以“9…”开头。 - Dave C
显示剩余7条评论

66

1
echo "System.err.print(Runtime.version().major())" | $JDK/bin/jshell 2>&1 > /dev/null - judovana
7
自Java10起,Runtime.version().major()已经被弃用,现在的等效方法是Runtime.version().feature()。请注意更新使用此功能。 - fidekild
现在它不起作用。 - Because i hate myself

64

那么从软件包元信息中获取版本呢:

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

打印出类似于:

1.7.0_13


11
哇,那真是让我大开眼界。虽然在我的情况下,我只想要版本的前两个部分,如下所示:Runtime.class.getPackage().getSpecificationVersion() - Wesley Hartford
12
在JDK9上,Runtime.class.getPackage().getImplementationVersion()似乎返回null - tresf
2
也许只有在 MANIFEST.MF 中定义才能起作用? - Aaron Digulla

44

这些文章似乎建议检查前缀为1.51.6,因为它符合正确的版本命名约定。

Sun技术文章


1
有没有一种方法可以获取它是Oracle还是Open? - Joe C
2
既然从Java 9开始版本控制语法已经改变,那么其他的答案就更有用了。 - ReinstateMonica3167040
1
若要回答 @JoeC 几年后的问题,请查看其他系统属性,尤其是以下六个:java.runtime.namejava.vendorjava.vm.{name,vendor}java.vm.specification.{name,vendor}。我相信前两个可能会被官方JVM/JLS规范半标准化,而其他可能现在已成为某种标准惯例。根据应用程序中确切的使用情况,通常其中一个或多个属性可以成为决定因素。 - Ti Strga

33

最简单的方法 (java.specification.version):

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

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

或类似于 (java.version):

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

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

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

或者如果您想要将其拆分成多个部分(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];

你使用的 java.runtime.version 版本在 Java 9 上出现了问题 (java.lang.ArrayIndexOutOfBoundsException)。 - Eugène Adell

13

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 :)
    }

1
version < 1.4f... 当 version = 1.4f 时会发生什么? - ADTC
啊,是的,你说得对 - 在上面的例子中不会捕获1.4f。该示例仅演示了Apache Commons Lang的常量作为Java属性的替代方法 :) - mvanle
你可以编辑答案并将其更改为 version <= 1.4f。不幸的是,SystemUtils 没有提供一个名为 isJavaVersionLessThan 的方法,但是(幸运的是)你也可以把遗留代码放在一个 else 块中,这样会更简洁。 - ADTC
“Err...” 捕捉 1.4 的 “dodgy clause”? 1.4f 不应该回退到旧代码吗? - ADTC
2
我建议使用以下代码:if (SystemUtils.IS_JAVA_1_5) { /* 1.5 特定代码 */ } else if (SystemUtils.isJavaVersionAtLeast(1.6f)) { /* 现代代码 */ } else { /* 回退到旧版代码 */ }。在上面是特定代码,在下面是通用代码,最底部是回退代码。 - ADTC
@ADTC:你说得对。你的结构比我的好。但是我想保留我的结构的原因是因为人们可以看到 SystemUtils.JAVA_VERSION_FLOAT 可以和/或必须与浮点字面量进行比较。这是我唯一的借口 :) - mvanle

11

请注意,在Java 9及以上版本中,命名约定有所不同。System.getProperty("java.version")返回的是"9"而不是"1.9"


8

无法运行,需要使用--pos来评估双倍:

    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;
}

7

以下是在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));
}

6
如果您可以依赖于Apache Utils,您可以使用org.apache.commons.lang3.SystemUtils。
    System.out.println("Is Java version at least 1.8: " + SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_1_8));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接