Skip to content

Commit

Permalink
Detect jdk major version using Runtime class (#408)
Browse files Browse the repository at this point in the history
in #407, the BlockHound class is detecting the current jdk major version using InstrumentationUtil.jdkMajorVersion() method that has been introduced in #407 PR (the new InstrumentationUtil.jdkMajorVersion() method is relying on the jdk Runtime.getRuntime() class).

Now, there is still another class (NativeWrappingClassFileTransformer) which needs to determine the current jdk major version. Let's update it in order to reuse the InstrumentationUtil instead of relying of java system properties.
  • Loading branch information
pderop committed Apr 17, 2024
1 parent 7d6e746 commit 62dd291
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 26 deletions.
8 changes: 3 additions & 5 deletions agent/src/main/java/reactor/blockhound/BlockHound.java
Expand Up @@ -134,8 +134,6 @@ public TypePool typePool(ClassFileLocator classFileLocator, ClassLoader classLoa
public static class Builder {

private final Map<String, Map<String, Set<String>>> blockingMethods = new HashMap<String, Map<String, Set<String>>>() {{
int jdkMajorVersion = InstrumentationUtils.getJdkMajorVersion();

put("java/lang/Object", new HashMap<String, Set<String>>() {{
put("wait", singleton("(J)V"));
}});
Expand Down Expand Up @@ -196,7 +194,7 @@ public static class Builder {
put("writeBytes", singleton("([BIIZ)V"));
}});

if (jdkMajorVersion >= 9) {
if (InstrumentationUtils.jdkMajorVersion >= 9) {
put("jdk/internal/misc/Unsafe", new HashMap<String, Set<String>>() {{
put("park", singleton("(ZJ)V"));
}});
Expand All @@ -213,15 +211,15 @@ public static class Builder {
}});
}

if (jdkMajorVersion < 19) {
if (InstrumentationUtils.jdkMajorVersion < 19) {
// for jdk version < 19, the native method for Thread.sleep is "sleep"
put("java/lang/Thread", new HashMap<String, Set<String>>() {{
put("sleep", singleton("(J)V"));
put("yield", singleton("()V"));
put("onSpinWait", singleton("()V"));
}});
}
else if (jdkMajorVersion >= 19 && jdkMajorVersion <= 21) {
else if (InstrumentationUtils.jdkMajorVersion >= 19 && InstrumentationUtils.jdkMajorVersion <= 21) {
// for jdk version in the range [19, 21], the native method for Thread.sleep is "sleep0"
put("java/lang/Thread", new HashMap<String, Set<String>>() {{
put("sleep0", singleton("(J)V"));
Expand Down
30 changes: 17 additions & 13 deletions agent/src/main/java/reactor/blockhound/InstrumentationUtils.java
Expand Up @@ -34,6 +34,20 @@

class InstrumentationUtils {

/**
* Constant used to indicate the current JDK major version (8,9,..22,...)
*/
static final int jdkMajorVersion;

static {
try {
jdkMajorVersion = getJdkMajorVersion();
}
catch (InvocationTargetException | IllegalAccessException e) {
throw new ExceptionInInitializerError(e);
}
}

static void injectBootstrapClasses(Instrumentation instrumentation, String... classNames) throws IOException {
File tempJarFile = File.createTempFile("BlockHound", ".jar");
tempJarFile.deleteOnExit();
Expand Down Expand Up @@ -83,7 +97,7 @@ public void visit(int version, int access, String name, String signature, String
*
* @return the current jdk major version (8, 9, 10, ... 22)
*/
static int getJdkMajorVersion() {
private static int getJdkMajorVersion() throws InvocationTargetException, IllegalAccessException {
Object version = getRuntimeVersion();

if (version == null) {
Expand All @@ -98,7 +112,7 @@ static int getJdkMajorVersion() {
*
* @return the detected JDK version object or null if not available
*/
private static Object getRuntimeVersion() {
private static Object getRuntimeVersion() throws InvocationTargetException, IllegalAccessException {
Runtime runtime = Runtime.getRuntime();
try {
Method versionMethod = runtime.getClass().getMethod("version");
Expand All @@ -109,11 +123,6 @@ private static Object getRuntimeVersion() {
// Method Runtime.version() not found -> return null, meaning JDK 8
return null; // JDK 8
}

catch (IllegalAccessException | InvocationTargetException e) {
// if the Runtime.version() method exists, we should be able to invoke it, consider this is an error state
throw new IllegalStateException("Could not invoke Runtime.version() method", e);
}
}

/**
Expand All @@ -122,7 +131,7 @@ private static Object getRuntimeVersion() {
* @param version the JDK version object
* @return the major version (9, 10, ...)
*/
private static int getRuntimeVersionFeature(Object version) {
private static int getRuntimeVersionFeature(Object version) throws InvocationTargetException, IllegalAccessException {
try {
Method featureMethod = version.getClass().getMethod("feature");
Object feature = featureMethod.invoke(version);
Expand All @@ -133,11 +142,6 @@ private static int getRuntimeVersionFeature(Object version) {
// Version.feature() method not found -> JDK 9 (because feature method is only available starting from JDK10 +)
return 9;
}

catch (IllegalAccessException | InvocationTargetException e) {
// if the Runtime.version().feature() method exists, we should be able to invoke it, consider this is an error state
throw new IllegalStateException("Could not invoke Runtime.version().feature() method", e);
}
}

}
Expand Up @@ -36,13 +36,7 @@ class NativeWrappingClassFileTransformer implements ClassFileTransformer {

private final Map<String, Map<String, Set<String>>> blockingMethods;

public static final boolean IS_JDK_18_OR_NEWER;

static {
String javaVersion = System.getProperty("java.specification.version");
double version = Double.parseDouble(javaVersion);
IS_JDK_18_OR_NEWER = version >= 18.0;
}
private static final int JDK_18 = 18;

NativeWrappingClassFileTransformer(final Map<String, Map<String, Set<String>>> blockingMethods) {
this.blockingMethods = blockingMethods;
Expand Down Expand Up @@ -116,7 +110,7 @@ public MethodVisitor visitMethod(int access, String name, String descriptor, Str
@Override
public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
// See #392
if (IS_JDK_18_OR_NEWER && descriptor.equals("Ljdk/internal/vm/annotation/IntrinsicCandidate;")) {
if (InstrumentationUtils.jdkMajorVersion >= JDK_18 && descriptor.equals("Ljdk/internal/vm/annotation/IntrinsicCandidate;")) {
return null; // remove the intrinsic annotation
}
return super.visitAnnotation(descriptor, visible);
Expand Down

0 comments on commit 62dd291

Please sign in to comment.