自Java 11起,Java编译器和运行时环境可以启用预览模式。这使得可以预览新的功能。 (JEP 12)
java --enable-preview
我该如何在Java内部检测JVM是否已启用预览模式?
我的目的是在应用程序状态页面/JSON中描述正在运行的容器,以便进行devops概述。
到目前为止,我已经查看了系统属性和标志,但都没有任何提示。
java --enable-preview
我该如何在Java内部检测JVM是否已启用预览模式?
我的目的是在应用程序状态页面/JSON中描述正在运行的容器,以便进行devops概述。
到目前为止,我已经查看了系统属性和标志,但都没有任何提示。
您可以检查Java类文件的minor_version。如果值为0xFFFF
则说明该类文件是使用 --enable-preview 编译的。详见https://stackoverflow.com/a/58821511/868941。
以下是一个简单的程序用于检查此内容(请注意,这是启用预览功能的Java 13代码!)。
public final class ClassFileVersion {
private final int major;
private final int minor;
private ClassFileVersion(int major, int minor) {
this.major = major;
this.minor = minor;
}
public static ClassFileVersion of(Class<?> classFile) throws IOException {
try (InputStream is = classFile.getResourceAsStream("/%s.class".formatted(classFile.getName().replace('.', '/')))) {
var buffer = new byte[8];
if (is.read(buffer) != buffer.length) {
throw new AssertionError("Not a Java Class File!");
}
return new ClassFileVersion(readUnsignedShort(buffer, 6), readUnsignedShort(buffer, 4));
}
}
public String getVersionNumber() {
return "%d.%d".formatted(major, minor);
}
public boolean isEnablePreview() {
return major >= 55 && minor == 0xFFFF;
}
@Override
public String toString() {
return (major < 49 ? "JDK " : "Java SE ") +
switch(major) {
case 45 -> "1.1";
case 46 -> "1.2";
case 47 -> "1.3";
case 48 -> "1.4";
case 49 -> "5";
case 50 -> "6";
case 51 -> "7";
case 52 -> "8";
case 53 -> "9";
case 54 -> "10";
case 55 -> "11";
case 56 -> "12";
case 57 -> "13";
case 58 -> "14";
default -> throw wrongVersion();
} +
switch(minor) {
case 0 -> "";
case 3 -> {
if (major != 45) {
throw wrongVersion();
}
yield "";
}
case 0xFFFF -> " --enable-preview";
default -> throw wrongVersion();
};
}
private static int readUnsignedShort(byte[] buffer, int offset) {
return ((buffer[offset] & 0xff) << 8) + (buffer[++offset] & 0xff);
}
private AssertionError wrongVersion() {
return new AssertionError("Wrong Java Class File Version: %d.%d".formatted(major, minor));
}
// to run this code (JDK 13 needed):
// java --enable-preview --source 13 ClassFileVersion.java
public static void main(String[] args) throws IOException {
// prints "Java SE 13 --enable-preview"
System.out.println(ClassFileVersion.of(ClassFileVersion.class));
}
}
--enable-preview
编译,而不是在运行时启用了预览。显然,如果结果为 true
,那么它必须是有效的,但是当类文件没有使用预览编译,但在运行时启用了预览时,结果将是错误的。 - Holger