diff --git a/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java b/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java index 8d51bba8c655..fe4c59bb8498 100644 --- a/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java +++ b/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java @@ -82,7 +82,6 @@ import com.oracle.svm.agent.tracing.core.Tracer; import com.oracle.svm.configure.trace.AccessAdvisor; import com.oracle.svm.core.c.function.CEntryPointOptions; -import com.oracle.svm.core.jni.JNIObjectHandles; import com.oracle.svm.core.jni.headers.JNIEnvironment; import com.oracle.svm.core.jni.headers.JNIFieldId; import com.oracle.svm.core.jni.headers.JNIMethodId; @@ -481,8 +480,7 @@ private static boolean handleInvokeMethod(JNIEnvironment jni, JNIObjectHandle th */ if (isInvoke && isClassNewInstance(jni, declaring, name)) { JNIObjectHandle clazz = getObjectArgument(thread, 1); - JNIMethodId result = newInstanceMethodID(jni, clazz); - traceReflectBreakpoint(jni, clazz, nullHandle(), callerClass, "newInstance", result.notEqual(nullHandle()), state.getFullStackTraceOrNull()); + traceReflectBreakpoint(jni, clazz, nullHandle(), callerClass, "newInstance", clazz.notEqual(nullHandle()), state.getFullStackTraceOrNull()); } return true; } @@ -529,26 +527,10 @@ private static boolean handleInvokeConstructor(JNIEnvironment jni, @SuppressWarn private static boolean newInstance(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); JNIObjectHandle self = getReceiver(thread); - JNIMethodId result = newInstanceMethodID(jni, self); - traceReflectBreakpoint(jni, self, nullHandle(), callerClass, bp.specification.methodName, result.notEqual(nullHandle()), state.getFullStackTraceOrNull()); + traceReflectBreakpoint(jni, self, nullHandle(), callerClass, bp.specification.methodName, self.notEqual(nullHandle()), state.getFullStackTraceOrNull()); return true; } - private static JNIMethodId newInstanceMethodID(JNIEnvironment jni, JNIObjectHandle clazz) { - JNIMethodId result = nullPointer(); - String name = ""; - String signature = "()V"; - if (clazz.notEqual(nullHandle())) { - try (CCharPointerHolder ctorName = toCString(name); CCharPointerHolder ctorSignature = toCString(signature)) { - result = jniFunctions().getGetMethodID().invoke(jni, clazz, ctorName.get(), ctorSignature.get()); - } - if (clearException(jni)) { - result = nullPointer(); - } - } - return result; - } - private static boolean newArrayInstance(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { JNIValue args = StackValue.get(2, JNIValue.class); args.addressOf(0).setObject(getObjectArgument(thread, 0)); @@ -799,14 +781,9 @@ private static boolean loadClass(JNIEnvironment jni, JNIObjectHandle thread, Bre observedExplicitLoadClassCallSites.put(location, Boolean.TRUE); } } - JNIObjectHandle self = getReceiver(thread); JNIObjectHandle name = getObjectArgument(thread, 1); String className = fromJniString(jni, name); - JNIObjectHandle clazz = Support.callObjectMethodL(jni, self, bp.method, name); - if (clearException(jni)) { - clazz = nullHandle(); - } - traceReflectBreakpoint(jni, bp.clazz, nullHandle(), callerClass, bp.specification.methodName, clazz.notEqual(nullHandle()), state.getFullStackTraceOrNull(), className); + traceReflectBreakpoint(jni, bp.clazz, nullHandle(), callerClass, bp.specification.methodName, className != null, state.getFullStackTraceOrNull(), className); return true; } @@ -858,70 +835,53 @@ private static boolean isLoadClassInvocation(JNIObjectHandle clazz, JNIMethodId } } - private static boolean findMethodHandle(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean findMethodHandle(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle declaringClass = getObjectArgument(thread, 1); JNIObjectHandle methodName = getObjectArgument(thread, 2); JNIObjectHandle methodType = getObjectArgument(thread, 3); - JNIObjectHandle result = Support.callObjectMethodLLL(jni, lookup, bp.method, declaringClass, methodName, methodType); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); - - return methodMethodHandle(jni, declaringClass, callerClass, methodName, getParamTypes(jni, methodType), result, state.getFullStackTraceOrNull()); + return methodMethodHandle(jni, declaringClass, callerClass, methodName, getParamTypes(jni, methodType), state.getFullStackTraceOrNull()); } - private static boolean findSpecialHandle(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean findSpecialHandle(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle declaringClass = getObjectArgument(thread, 1); JNIObjectHandle methodName = getObjectArgument(thread, 2); JNIObjectHandle methodType = getObjectArgument(thread, 3); - JNIObjectHandle specialCaller = getObjectArgument(thread, 4); - JNIObjectHandle result = Support.callObjectMethodLLLL(jni, lookup, bp.method, declaringClass, methodName, methodType, specialCaller); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); - - return methodMethodHandle(jni, declaringClass, callerClass, methodName, getParamTypes(jni, methodType), result, state.getFullStackTraceOrNull()); + return methodMethodHandle(jni, declaringClass, callerClass, methodName, getParamTypes(jni, methodType), state.getFullStackTraceOrNull()); } - private static boolean bindHandle(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean bindHandle(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle receiver = getObjectArgument(thread, 1); JNIObjectHandle methodName = getObjectArgument(thread, 2); JNIObjectHandle methodType = getObjectArgument(thread, 3); - JNIObjectHandle result = Support.callObjectMethodLLL(jni, lookup, bp.method, receiver, methodName, methodType); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); - JNIObjectHandle declaringClass = Support.callObjectMethod(jni, receiver, agent.handles().javaLangObjectGetClass); if (clearException(jni)) { declaringClass = nullHandle(); } - return methodMethodHandle(jni, declaringClass, callerClass, methodName, getParamTypes(jni, methodType), result, state.getFullStackTraceOrNull()); + return methodMethodHandle(jni, declaringClass, callerClass, methodName, getParamTypes(jni, methodType), state.getFullStackTraceOrNull()); } private static boolean methodMethodHandle(JNIEnvironment jni, JNIObjectHandle declaringClass, JNIObjectHandle callerClass, JNIObjectHandle nameHandle, JNIObjectHandle paramTypesHandle, - JNIObjectHandle result, JNIMethodId[] stackTrace) { + JNIMethodId[] stackTrace) { String name = fromJniString(jni, nameHandle); Object paramTypes = getClassArrayNames(jni, paramTypesHandle); - traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findMethodHandle", result.notEqual(nullHandle()), stackTrace, name, paramTypes); + traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findMethodHandle", declaringClass.notEqual(nullHandle()) && name != null, stackTrace, name, paramTypes); return true; } - private static boolean findConstructorHandle(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean findConstructorHandle(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle declaringClass = getObjectArgument(thread, 1); JNIObjectHandle methodType = getObjectArgument(thread, 2); - JNIObjectHandle result = Support.callObjectMethodLL(jni, lookup, bp.method, declaringClass, methodType); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); - Object paramTypes = getClassArrayNames(jni, getParamTypes(jni, methodType)); - traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findConstructorHandle", result.notEqual(nullHandle()), state.getFullStackTraceOrNull(), paramTypes); + traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findConstructorHandle", declaringClass.notEqual(nullHandle()), state.getFullStackTraceOrNull(), paramTypes); return true; } @@ -933,42 +893,29 @@ private static JNIObjectHandle getParamTypes(JNIEnvironment jni, JNIObjectHandle return paramTypesHandle; } - private static boolean findFieldHandle(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean findFieldHandle(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle declaringClass = getObjectArgument(thread, 1); JNIObjectHandle fieldName = getObjectArgument(thread, 2); - JNIObjectHandle fieldType = getObjectArgument(thread, 3); - - JNIObjectHandle result = Support.callObjectMethodLLL(jni, lookup, bp.method, declaringClass, fieldName, fieldType); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); String name = fromJniString(jni, fieldName); - traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findFieldHandle", result.notEqual(nullHandle()), state.getFullStackTraceOrNull(), name); + traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findFieldHandle", declaringClass.notEqual(nullHandle()) && name != null, state.getFullStackTraceOrNull(), name); return true; } private static boolean findClass(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle className = getObjectArgument(thread, 1); - JNIObjectHandle result = Support.callObjectMethodL(jni, lookup, bp.method, className); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); - String name = fromJniString(jni, className); - traceReflectBreakpoint(jni, bp.clazz, nullHandle(), callerClass, "findClass", result.notEqual(nullHandle()), state.getFullStackTraceOrNull(), name); + traceReflectBreakpoint(jni, bp.clazz, nullHandle(), callerClass, "findClass", name != null, state.getFullStackTraceOrNull(), name); return true; } - private static boolean unreflectField(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean unreflectField(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getReceiver(thread); JNIObjectHandle field = getObjectArgument(thread, 1); - JNIObjectHandle result = Support.callObjectMethodL(jni, lookup, bp.method, field); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessException); - JNIObjectHandle declaringClass = Support.callObjectMethod(jni, field, agent.handles().javaLangReflectMemberGetDeclaringClass); if (clearException(jni)) { declaringClass = nullHandle(); @@ -980,46 +927,34 @@ private static boolean unreflectField(JNIEnvironment jni, JNIObjectHandle thread } String fieldName = fromJniString(jni, fieldNameHandle); - traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "unreflectField", result.notEqual(nullHandle()), state.getFullStackTraceOrNull(), fieldName); + traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "unreflectField", declaringClass.notEqual(nullHandle()) && fieldName != null, state.getFullStackTraceOrNull(), + fieldName); return true; } - private static boolean asInterfaceInstance(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state) { + private static boolean asInterfaceInstance(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state) { JNIObjectHandle callerClass = state.getDirectCallerClass(); JNIObjectHandle intfc = getObjectArgument(thread, 0); - JNIObjectHandle methodHandle = getObjectArgument(thread, 1); - - JNIObjectHandle result = Support.callStaticObjectMethodLL(jni, bp.clazz, bp.method, intfc, methodHandle); - result = shouldIncludeMethod(jni, result, agent.handles().javaLangInvokeWrongMethodTypeException, agent.handles().javaLangIllegalArgumentException); JNIObjectHandle intfcNameHandle = Support.callObjectMethod(jni, intfc, agent.handles().javaLangClassGetName); if (clearException(jni)) { intfcNameHandle = nullHandle(); } String intfcName = fromJniString(jni, intfcNameHandle); - traceReflectBreakpoint(jni, intfc, nullHandle(), callerClass, "asInterfaceInstance", result.notEqual(nullHandle()), state.getFullStackTraceOrNull()); + traceReflectBreakpoint(jni, intfc, nullHandle(), callerClass, "asInterfaceInstance", intfcName != null, state.getFullStackTraceOrNull()); String[] intfcNames = new String[]{intfcName}; - traceReflectBreakpoint(jni, nullHandle(), nullHandle(), callerClass, "newMethodHandleProxyInstance", result.notEqual(nullHandle()), state.getFullStackTraceOrNull(), (Object) intfcNames); + traceReflectBreakpoint(jni, nullHandle(), nullHandle(), callerClass, "newMethodHandleProxyInstance", intfcName != null, state.getFullStackTraceOrNull(), (Object) intfcNames); return true; } - private static boolean constantBootstrapGetStaticFinal(JNIEnvironment jni, JNIObjectHandle thread, Breakpoint bp, InterceptedState state, boolean hasDeclaringClass) { + private static boolean constantBootstrapGetStaticFinal(JNIEnvironment jni, JNIObjectHandle thread, @SuppressWarnings("unused") Breakpoint bp, InterceptedState state, boolean hasDeclaringClass) { JNIObjectHandle callerClass = state.getDirectCallerClass(); - JNIObjectHandle lookup = getObjectArgument(thread, 0); JNIObjectHandle fieldName = getObjectArgument(thread, 1); JNIObjectHandle type = getObjectArgument(thread, 2); JNIObjectHandle declaringClass = hasDeclaringClass ? getObjectArgument(thread, 3) : type; - JNIObjectHandle result; - if (hasDeclaringClass) { - result = Support.callStaticObjectMethodLLLL(jni, bp.clazz, bp.method, lookup, fieldName, type, declaringClass); - } else { - result = Support.callStaticObjectMethodLLL(jni, bp.clazz, bp.method, lookup, fieldName, type); - } - result = shouldIncludeMethod(jni, result, agent.handles().javaLangIllegalAccessError); - String name = fromJniString(jni, fieldName); - traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findFieldHandle", result.notEqual(nullHandle()), state.getFullStackTraceOrNull(), name); + traceReflectBreakpoint(jni, declaringClass, nullHandle(), callerClass, "findFieldHandle", declaringClass.notEqual(nullHandle()) && name != null, state.getFullStackTraceOrNull(), name); return true; } @@ -1058,24 +993,6 @@ private static boolean methodTypeFromDescriptor(JNIEnvironment jni, JNIObjectHan return true; } - private static JNIObjectHandle shouldIncludeMethod(JNIEnvironment jni, JNIObjectHandle result, JNIObjectHandle... acceptedExceptions) { - JNIObjectHandle exception = handleException(jni, true); - if (exception.notEqual(nullHandle())) { - for (JNIObjectHandle acceptedException : acceptedExceptions) { - if (jniFunctions().getIsInstanceOf().invoke(jni, exception, acceptedException)) { - /* - * We include methods if the lookup returned an IllegalAccessException or a - * WrongMethodTypeException to make sure the right exception is thrown at - * runtime, instead of a NoSuchMethodException. - */ - return JNIObjectHandles.createLocal(Boolean.TRUE); - } - } - return nullHandle(); - } - return result; - } - /** * We have to find a class that captures a lambda function so it can be registered by the agent. * We have to get a SerializedLambda instance first. After that we get a lambda capturing class diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java index 9b76c277294f..b87fdc9959c4 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/ClassForNameSupport.java @@ -55,14 +55,13 @@ public static void registerClass(Class clazz) { return; // must be defined at runtime before it can be looked up } String name = clazz.getName(); - if (!singleton().knownClasses.containsKey(name) || !(singleton().knownClasses.get(name) instanceof Throwable)) { - /* - * If the class has already been seen as throwing an error, we don't overwrite this - * error - */ - VMError.guarantee(!singleton().knownClasses.containsKey(name) || singleton().knownClasses.get(name) == clazz); - singleton().knownClasses.put(name, clazz); - } + Object currentValue = singleton().knownClasses.get(name); + VMError.guarantee(currentValue == null || currentValue == clazz || currentValue instanceof Throwable, + "Invalid Class.forName value for %s: %s", name, currentValue); + /* + * If the class has already been seen as throwing an error, we don't overwrite this error + */ + singleton().knownClasses.putIfAbsent(name, clazz); } @Platforms(Platform.HOSTED_ONLY.class) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MissingReflectionRegistrationUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MissingReflectionRegistrationUtils.java index 86fadb34a291..8ca8222d8ccd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MissingReflectionRegistrationUtils.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MissingReflectionRegistrationUtils.java @@ -56,8 +56,10 @@ public static void forField(Class declaringClass, String fieldName) { public static void forMethod(Class declaringClass, String methodName, Class[] paramTypes) { StringJoiner paramTypeNames = new StringJoiner(", ", "(", ")"); - for (Class paramType : paramTypes) { - paramTypeNames.add(paramType.getTypeName()); + if (paramTypes != null) { + for (Class paramType : paramTypes) { + paramTypeNames.add(paramType.getTypeName()); + } } MissingReflectionRegistrationError exception = new MissingReflectionRegistrationError(errorMessage("access method", declaringClass.getTypeName() + "#" + methodName + paramTypeNames), diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java index 9bc751363555..420406307d08 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java @@ -30,9 +30,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.impl.ConfigurationCondition; -import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; +import org.graalvm.nativeimage.hosted.RuntimeReflection; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; @@ -41,12 +39,10 @@ @AutomaticallyRegisteredFeature public class AnnotationFeature implements InternalFeature { - private RuntimeReflectionSupport runtimeReflectionSupport; private final Set> processedTypes = ConcurrentHashMap.newKeySet(); @Override public void duringSetup(DuringSetupAccess access) { - runtimeReflectionSupport = ImageSingletons.lookup(RuntimeReflectionSupport.class); access.registerObjectReplacer(this::registerDeclaredMethods); } @@ -62,7 +58,7 @@ private Object registerDeclaredMethods(Object obj) { if (obj instanceof Annotation annotation && Proxy.isProxyClass(annotation.getClass())) { Class annotationType = annotation.annotationType(); if (processedTypes.add(annotationType)) { - runtimeReflectionSupport.registerAllDeclaredMethodsQuery(ConfigurationCondition.alwaysTrue(), false, annotationType); + RuntimeReflection.registerAllDeclaredMethods(annotationType); } } return obj; diff --git a/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java b/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java index 0580eededf6a..c3e2cd440ca4 100644 --- a/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java +++ b/substratevm/src/com.oracle.svm.polyglot/src/com/oracle/svm/polyglot/scala/ScalaFeature.java @@ -98,7 +98,7 @@ private static void initializeScalaEnumerations(BeforeAnalysisAccess beforeAnaly access.findSubclasses(scalaEnum).forEach(enumClass -> { /* this is based on implementation of scala.Enumeration.populateNamesMap */ - RuntimeReflection.register(enumClass.getDeclaredFields()); + RuntimeReflection.registerAllDeclaredFields(enumClass); // all method relevant for Enums Method[] relevantMethods = Arrays.stream(enumClass.getDeclaredMethods()) .filter(m -> m.getParameterTypes().length == 0 && diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/SecurityServiceTest.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/SecurityServiceTest.java index e648f3f0b11a..01e55127a7d0 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/SecurityServiceTest.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/SecurityServiceTest.java @@ -64,7 +64,7 @@ public void duringSetup(final DuringSetupAccess access) { // register the service implementation for reflection explicitly, // non-standard services are not processed automatically RuntimeReflection.register(NoOpImpl.class); - RuntimeReflection.register(NoOpImpl.class.getConstructors()); + RuntimeReflection.register(NoOpImpl.class.getDeclaredConstructors()); } }