diff --git a/terminator-commons/src/main/java/io/github/algomaster99/terminator/commons/fingerprint/classfile/RuntimeClass.java b/terminator-commons/src/main/java/io/github/algomaster99/terminator/commons/fingerprint/classfile/RuntimeClass.java index 77835c77..9ccd48d2 100644 --- a/terminator-commons/src/main/java/io/github/algomaster99/terminator/commons/fingerprint/classfile/RuntimeClass.java +++ b/terminator-commons/src/main/java/io/github/algomaster99/terminator/commons/fingerprint/classfile/RuntimeClass.java @@ -37,4 +37,16 @@ public static boolean isGeneratedClassExtendingMagicAccessor(byte[] classfileByt return false; } } + + /** + * During the runtime the jvm binds methodhandles to the class {@link java.lang.invoke.BoundMethodHandle}. + * These classes are generated at runtime and should be ignored. We can identify them by checking if the super class is {@link java.lang.invoke.BoundMethodHandle}. + * @param classfileBytes the class file bytes + * @return true if the class is a bound method handle, false otherwise. + */ + public static boolean isBoundMethodHandle(byte[] classfileBytes) { + ClassReader reader = new ClassReader(classfileBytes); + System.err.println(reader.getSuperName()); + return reader.getSuperName().equals("java/lang/invoke/BoundMethodHandle"); + } } diff --git a/watchdog-agent/src/main/java/io/github/algomaster99/Terminator.java b/watchdog-agent/src/main/java/io/github/algomaster99/Terminator.java index 32a9abf9..2bec58dc 100644 --- a/watchdog-agent/src/main/java/io/github/algomaster99/Terminator.java +++ b/watchdog-agent/src/main/java/io/github/algomaster99/Terminator.java @@ -33,12 +33,8 @@ public byte[] transform( private static byte[] isLoadedClassWhitelisted(String className, byte[] classfileBuffer) { Map> fingerprints = options.getFingerprints(); if (RuntimeClass.isProxyClass(classfileBuffer) - || RuntimeClass.isGeneratedClassExtendingMagicAccessor(classfileBuffer)) { - return classfileBuffer; - } - if (className.contains("$")) { - // FIXME: we need to check inner classes without loading them. Maybe add the hashes for inner classes in the - // fingerprints? + || RuntimeClass.isGeneratedClassExtendingMagicAccessor(classfileBuffer) + || RuntimeClass.isBoundMethodHandle(classfileBuffer)) { return classfileBuffer; } for (String expectedClassName : fingerprints.keySet()) { diff --git a/watchdog-agent/src/test/java/OptionsTest.java b/watchdog-agent/src/test/java/OptionsTest.java index aabcccc1..b3c9c3e1 100644 --- a/watchdog-agent/src/test/java/OptionsTest.java +++ b/watchdog-agent/src/test/java/OptionsTest.java @@ -66,4 +66,11 @@ void verifyJdkIndexerFindsOrgXmlSax() throws Exception { var var = options.getJdkFingerprints().keySet().stream().collect(Collectors.toSet()); assertThat(var).contains("org/xml/sax/helpers/NamespaceSupport"); } + + @Test + void verifyJdkIndexerFindsMethodHandle() throws Exception { + Options options = new Options("skipShutdown=true"); + boolean containsKey = options.getJdkFingerprints().containsKey("java/lang/invoke/BoundMethodHandle"); + assertThat(containsKey).isTrue(); + } }