DBZ-3993 Reflectively invoking Runtime.version();

As that API is only available from Java 9 onwards, calling it will cause
a compilation failure when compiling with --release.
This commit is contained in:
Gunnar Morling 2021-10-14 12:32:52 +02:00 committed by Chris Cranford
parent ae1ba98591
commit 26f13d83d5
2 changed files with 51 additions and 5 deletions

View File

@ -5,6 +5,17 @@
*/
package io.debezium.util;
import static java.lang.invoke.MethodType.methodType;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.debezium.DebeziumException;
/**
* Utility class dealing with Java version information.
*
@ -12,20 +23,52 @@
*/
public class JvmVersionUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(JvmVersionUtil.class);
private static final int FEATURE_VERSION = determineFeatureVersion();
private JvmVersionUtil() {
}
/**
* Returns the feature version of the current JVM, e.g. 8 or 17.
*/
public static int getFeatureVersion() {
private static int determineFeatureVersion() {
int featureVersion;
// Trying Runtime.version().version().get(0) at first; this will return the major version on Java 9+
//
// Using method handles so to be able to compile this code to Java 1.8 byte code level using the --release
// parameter
//
// Using the List<Integer> version() approach, so to avoid calling the deprecated majorVersion() method
try {
return Runtime.version().feature();
ClassLoader classLoader = JvmVersionUtil.class.getClassLoader();
Class<?> versionClass = classLoader.loadClass("java.lang.Runtime$Version");
MethodHandle versionHandle = MethodHandles.lookup().findStatic(Runtime.class, "version", methodType(versionClass));
MethodHandle versionListHandle = MethodHandles.lookup().findVirtual(versionClass, "version", methodType(List.class));
try {
Object version = versionHandle.invoke();
List<Integer> versions = (List<Integer>) versionListHandle.bindTo(version).invoke();
featureVersion = versions.get(0);
}
catch (Throwable e) {
throw new DebeziumException("Couldn't determine runtime version", e);
}
}
// The version() is only available on Java 9 and later
catch (NoSuchMethodError nsme) {
// The version() method is only available on Java 9 and later
catch (ClassNotFoundException | NoSuchMethodError | NoSuchMethodException | IllegalAccessException nsme) {
final String specVersion = System.getProperty("java.specification.version");
return Integer.parseInt(specVersion.substring(specVersion.indexOf('.') + 1));
featureVersion = Integer.parseInt(specVersion.substring(specVersion.indexOf('.') + 1));
}
LOGGER.debug("Determined Java version: {}", featureVersion);
return featureVersion;
}
public static int getFeatureVersion() {
return FEATURE_VERSION;
}
}

View File

@ -55,6 +55,9 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Can't use the (generally preferable) release option yet, as the
Cassandra connector still needs to be built with Java 1.8 which
isn't aware of this option -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>