@@ -136,6 +136,9 @@ final class BreakpointInterceptor {
136136 /** Enables experimental support for class definitions via {@code ClassLoader.defineClass}. */
137137 private static boolean experimentalClassDefineSupport = false ;
138138
139+ /** Enables tracking of reflection queries for fine-tuned configuration. */
140+ private static boolean trackReflectionMetadata = false ;
141+
139142 /**
140143 * Locations in methods where explicit calls to {@code ClassLoader.loadClass} have been found.
141144 */
@@ -367,6 +370,52 @@ private static boolean getEnclosingMethod(JNIEnvironment jni, Breakpoint bp, Int
367370 return true ;
368371 }
369372
373+ private static boolean invokeMethod (JNIEnvironment jni , Breakpoint bp , InterceptedState state ) {
374+ JNIObjectHandle callerClass = state .getDirectCallerClass ();
375+ JNIObjectHandle self = getObjectArgument (0 );
376+
377+ JNIObjectHandle declaring = Support .callObjectMethod (jni , self , agent .handles ().javaLangReflectMemberGetDeclaringClass );
378+ if (clearException (jni )) {
379+ declaring = nullHandle ();
380+ }
381+
382+ JNIObjectHandle nameHandle = Support .callObjectMethod (jni , self , agent .handles ().javaLangReflectMemberGetName );
383+ if (clearException (jni )) {
384+ nameHandle = nullHandle ();
385+ }
386+ String name = fromJniString (jni , nameHandle );
387+
388+ JNIObjectHandle paramTypesHandle = Support .callObjectMethod (jni , self , agent .handles ().javaLangReflectExecutableGetParameterTypes );
389+ if (clearException (jni )) {
390+ paramTypesHandle = nullHandle ();
391+ }
392+ Object paramTypes = getClassArrayNames (jni , paramTypesHandle );
393+
394+ traceBreakpoint (jni , declaring , declaring , callerClass , bp .specification .methodName , self .notEqual (nullHandle ()), state .getFullStackTraceOrNull (), name , paramTypes );
395+ return true ;
396+ }
397+
398+ private static boolean invokeConstructor (JNIEnvironment jni , @ SuppressWarnings ("unused" ) Breakpoint bp , InterceptedState state ) {
399+ JNIObjectHandle callerClass = state .getDirectCallerClass ();
400+ JNIObjectHandle self = getObjectArgument (0 );
401+
402+ JNIObjectHandle declaring = Support .callObjectMethod (jni , self , agent .handles ().javaLangReflectMemberGetDeclaringClass );
403+ if (clearException (jni )) {
404+ declaring = nullHandle ();
405+ }
406+
407+ String name = "<init>" ;
408+
409+ JNIObjectHandle paramTypesHandle = Support .callObjectMethod (jni , self , agent .handles ().javaLangReflectExecutableGetParameterTypes );
410+ if (clearException (jni )) {
411+ paramTypesHandle = nullHandle ();
412+ }
413+ Object paramTypes = getClassArrayNames (jni , paramTypesHandle );
414+
415+ traceBreakpoint (jni , declaring , declaring , callerClass , "invoke" , self .notEqual (nullHandle ()), state .getFullStackTraceOrNull (), name , paramTypes );
416+ return true ;
417+ }
418+
370419 private static boolean newInstance (JNIEnvironment jni , Breakpoint bp , InterceptedState state ) {
371420 JNIObjectHandle callerClass = state .getDirectCallerClass ();
372421 JNIMethodId result = nullPointer ();
@@ -1068,12 +1117,13 @@ private static void onClassFileLoadHook(@SuppressWarnings("unused") JvmtiEnv jvm
10681117
10691118 public static void onLoad (JvmtiEnv jvmti , JvmtiEventCallbacks callbacks , Tracer writer , NativeImageAgent nativeImageTracingAgent ,
10701119 Supplier <InterceptedState > currentThreadJavaStackAccessSupplier ,
1071- boolean exptlClassLoaderSupport , boolean exptlClassDefineSupport ) {
1120+ boolean exptlClassLoaderSupport , boolean exptlClassDefineSupport , boolean trackReflectionData ) {
10721121 BreakpointInterceptor .tracer = writer ;
10731122 BreakpointInterceptor .agent = nativeImageTracingAgent ;
10741123 BreakpointInterceptor .interceptedStateSupplier = currentThreadJavaStackAccessSupplier ;
10751124 BreakpointInterceptor .experimentalClassLoaderSupport = exptlClassLoaderSupport ;
10761125 BreakpointInterceptor .experimentalClassDefineSupport = exptlClassDefineSupport ;
1126+ BreakpointInterceptor .trackReflectionMetadata = trackReflectionData ;
10771127
10781128 JvmtiCapabilities capabilities = UnmanagedMemory .calloc (SizeOf .get (JvmtiCapabilities .class ));
10791129 check (jvmti .getFunctions ().GetCapabilities ().invoke (jvmti , capabilities ));
@@ -1122,7 +1172,13 @@ public static void onVMInit(JvmtiEnv jvmti, JNIEnvironment jni) {
11221172
11231173 JNIObjectHandle lastClass = nullHandle ();
11241174 String lastClassName = null ;
1125- for (BreakpointSpecification br : BREAKPOINT_SPECIFICATIONS ) {
1175+ BreakpointSpecification [] breakpointSpecifications = BREAKPOINT_SPECIFICATIONS ;
1176+ if (trackReflectionMetadata ) {
1177+ breakpointSpecifications = new BreakpointSpecification [BREAKPOINT_SPECIFICATIONS .length + REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS .length ];
1178+ System .arraycopy (BREAKPOINT_SPECIFICATIONS , 0 , breakpointSpecifications , 0 , BREAKPOINT_SPECIFICATIONS .length );
1179+ System .arraycopy (REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS , 0 , breakpointSpecifications , BREAKPOINT_SPECIFICATIONS .length , REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS .length );
1180+ }
1181+ for (BreakpointSpecification br : breakpointSpecifications ) {
11261182 JNIObjectHandle clazz = nullHandle ();
11271183 if (lastClassName != null && lastClassName .equals (br .className )) {
11281184 clazz = lastClass ;
@@ -1245,24 +1301,18 @@ private interface BreakpointHandler {
12451301 brk ("java/lang/Class" , "forName" , "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;" , BreakpointInterceptor ::forName ),
12461302
12471303 brk ("java/lang/Class" , "getFields" , "()[Ljava/lang/reflect/Field;" , BreakpointInterceptor ::getFields ),
1248- brk ("java/lang/Class" , "getMethods" , "()[Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getMethods ),
1249- brk ("java/lang/Class" , "getConstructors" , "()[Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructors ),
12501304 brk ("java/lang/Class" , "getClasses" , "()[Ljava/lang/Class;" , BreakpointInterceptor ::getClasses ),
12511305 brk ("java/lang/Class" , "getDeclaredFields" , "()[Ljava/lang/reflect/Field;" , BreakpointInterceptor ::getDeclaredFields ),
1252- brk ("java/lang/Class" , "getDeclaredMethods" , "()[Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getDeclaredMethods ),
1253- brk ("java/lang/Class" , "getDeclaredConstructors" , "()[Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getDeclaredConstructors ),
12541306 brk ("java/lang/Class" , "getDeclaredClasses" , "()[Ljava/lang/Class;" , BreakpointInterceptor ::getDeclaredClasses ),
12551307
12561308 brk ("java/lang/Class" , "getField" , "(Ljava/lang/String;)Ljava/lang/reflect/Field;" , BreakpointInterceptor ::getField ),
12571309 brk ("java/lang/Class" , "getDeclaredField" , "(Ljava/lang/String;)Ljava/lang/reflect/Field;" , BreakpointInterceptor ::getDeclaredField ),
1258- brk ("java/lang/Class" , "getMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getMethod ),
1259- brk ("java/lang/Class" , "getConstructor" , "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructor ),
1260- brk ("java/lang/Class" , "getDeclaredMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getDeclaredMethod ),
1261- brk ("java/lang/Class" , "getDeclaredConstructor" , "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructor ),
12621310
12631311 brk ("java/lang/Class" , "getEnclosingMethod" , "()Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getEnclosingMethod ),
12641312 brk ("java/lang/Class" , "getEnclosingConstructor" , "()Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getEnclosingMethod ),
12651313
1314+ brk ("java/lang/reflect/Method" , "invoke" , "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;" , BreakpointInterceptor ::invokeMethod ),
1315+ brk ("java/lang/reflect/Constructor" , "newInstance" , "([Ljava/lang/Object;)Ljava/lang/Object;" , BreakpointInterceptor ::invokeConstructor ),
12661316 brk ("java/lang/Class" , "newInstance" , "()Ljava/lang/Object;" , BreakpointInterceptor ::newInstance ),
12671317 brk ("java/lang/reflect/Array" , "newInstance" , "(Ljava/lang/Class;I)Ljava/lang/Object;" , BreakpointInterceptor ::newArrayInstance ),
12681318 brk ("java/lang/reflect/Array" , "newInstance" , "(Ljava/lang/Class;[I)Ljava/lang/Object;" , BreakpointInterceptor ::newArrayInstanceMulti ),
@@ -1353,6 +1403,18 @@ private interface BreakpointHandler {
13531403 private static final BreakpointSpecification CLASSLOADER_LOAD_CLASS_BREAKPOINT_SPECIFICATION = optionalBrk ("java/lang/ClassLoader" , "loadClass" ,
13541404 "(Ljava/lang/String;)Ljava/lang/Class;" , BreakpointInterceptor ::loadClass );
13551405
1406+ private static final BreakpointSpecification [] REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS = {
1407+ brk ("java/lang/Class" , "getMethods" , "()[Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getMethods ),
1408+ brk ("java/lang/Class" , "getConstructors" , "()[Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructors ),
1409+ brk ("java/lang/Class" , "getDeclaredMethods" , "()[Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getDeclaredMethods ),
1410+ brk ("java/lang/Class" , "getDeclaredConstructors" , "()[Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getDeclaredConstructors ),
1411+
1412+ brk ("java/lang/Class" , "getMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getMethod ),
1413+ brk ("java/lang/Class" , "getConstructor" , "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructor ),
1414+ brk ("java/lang/Class" , "getDeclaredMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getDeclaredMethod ),
1415+ brk ("java/lang/Class" , "getDeclaredConstructor" , "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructor ),
1416+ };
1417+
13561418 private static BreakpointSpecification brk (String className , String methodName , String signature , BreakpointHandler handler ) {
13571419 return new BreakpointSpecification (className , methodName , signature , handler , false );
13581420 }
0 commit comments