@@ -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,31 @@ 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 ().javaLangReflectMethodGetParameterTypes );
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+
370398 private static boolean newInstance (JNIEnvironment jni , Breakpoint bp , InterceptedState state ) {
371399 JNIObjectHandle callerClass = state .getDirectCallerClass ();
372400 JNIMethodId result = nullPointer ();
@@ -1068,12 +1096,13 @@ private static void onClassFileLoadHook(@SuppressWarnings("unused") JvmtiEnv jvm
10681096
10691097 public static void onLoad (JvmtiEnv jvmti , JvmtiEventCallbacks callbacks , Tracer writer , NativeImageAgent nativeImageTracingAgent ,
10701098 Supplier <InterceptedState > currentThreadJavaStackAccessSupplier ,
1071- boolean exptlClassLoaderSupport , boolean exptlClassDefineSupport ) {
1099+ boolean exptlClassLoaderSupport , boolean exptlClassDefineSupport , boolean trackReflectionData ) {
10721100 BreakpointInterceptor .tracer = writer ;
10731101 BreakpointInterceptor .agent = nativeImageTracingAgent ;
10741102 BreakpointInterceptor .interceptedStateSupplier = currentThreadJavaStackAccessSupplier ;
10751103 BreakpointInterceptor .experimentalClassLoaderSupport = exptlClassLoaderSupport ;
10761104 BreakpointInterceptor .experimentalClassDefineSupport = exptlClassDefineSupport ;
1105+ BreakpointInterceptor .trackReflectionMetadata = trackReflectionData ;
10771106
10781107 JvmtiCapabilities capabilities = UnmanagedMemory .calloc (SizeOf .get (JvmtiCapabilities .class ));
10791108 check (jvmti .getFunctions ().GetCapabilities ().invoke (jvmti , capabilities ));
@@ -1122,7 +1151,13 @@ public static void onVMInit(JvmtiEnv jvmti, JNIEnvironment jni) {
11221151
11231152 JNIObjectHandle lastClass = nullHandle ();
11241153 String lastClassName = null ;
1125- for (BreakpointSpecification br : BREAKPOINT_SPECIFICATIONS ) {
1154+ BreakpointSpecification [] breakpointSpecifications = BREAKPOINT_SPECIFICATIONS ;
1155+ if (trackReflectionMetadata ) {
1156+ breakpointSpecifications = new BreakpointSpecification [BREAKPOINT_SPECIFICATIONS .length + REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS .length ];
1157+ System .arraycopy (BREAKPOINT_SPECIFICATIONS , 0 , breakpointSpecifications , 0 , BREAKPOINT_SPECIFICATIONS .length );
1158+ System .arraycopy (REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS , 0 , breakpointSpecifications , BREAKPOINT_SPECIFICATIONS .length , REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS .length );
1159+ }
1160+ for (BreakpointSpecification br : breakpointSpecifications ) {
11261161 JNIObjectHandle clazz = nullHandle ();
11271162 if (lastClassName != null && lastClassName .equals (br .className )) {
11281163 clazz = lastClass ;
@@ -1245,24 +1280,17 @@ private interface BreakpointHandler {
12451280 brk ("java/lang/Class" , "forName" , "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;" , BreakpointInterceptor ::forName ),
12461281
12471282 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 ),
12501283 brk ("java/lang/Class" , "getClasses" , "()[Ljava/lang/Class;" , BreakpointInterceptor ::getClasses ),
12511284 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 ),
12541285 brk ("java/lang/Class" , "getDeclaredClasses" , "()[Ljava/lang/Class;" , BreakpointInterceptor ::getDeclaredClasses ),
12551286
12561287 brk ("java/lang/Class" , "getField" , "(Ljava/lang/String;)Ljava/lang/reflect/Field;" , BreakpointInterceptor ::getField ),
12571288 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 ),
12621289
12631290 brk ("java/lang/Class" , "getEnclosingMethod" , "()Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getEnclosingMethod ),
12641291 brk ("java/lang/Class" , "getEnclosingConstructor" , "()Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getEnclosingMethod ),
12651292
1293+ brk ("java/lang/reflect/Method" , "invoke" , "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;" , BreakpointInterceptor ::invokeMethod ),
12661294 brk ("java/lang/Class" , "newInstance" , "()Ljava/lang/Object;" , BreakpointInterceptor ::newInstance ),
12671295 brk ("java/lang/reflect/Array" , "newInstance" , "(Ljava/lang/Class;I)Ljava/lang/Object;" , BreakpointInterceptor ::newArrayInstance ),
12681296 brk ("java/lang/reflect/Array" , "newInstance" , "(Ljava/lang/Class;[I)Ljava/lang/Object;" , BreakpointInterceptor ::newArrayInstanceMulti ),
@@ -1353,6 +1381,18 @@ private interface BreakpointHandler {
13531381 private static final BreakpointSpecification CLASSLOADER_LOAD_CLASS_BREAKPOINT_SPECIFICATION = optionalBrk ("java/lang/ClassLoader" , "loadClass" ,
13541382 "(Ljava/lang/String;)Ljava/lang/Class;" , BreakpointInterceptor ::loadClass );
13551383
1384+ private static final BreakpointSpecification [] REFLECTION_QUERIES_BREAKPOINT_SPECIFICATIONS = {
1385+ brk ("java/lang/Class" , "getMethods" , "()[Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getMethods ),
1386+ brk ("java/lang/Class" , "getConstructors" , "()[Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructors ),
1387+ brk ("java/lang/Class" , "getDeclaredMethods" , "()[Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getDeclaredMethods ),
1388+ brk ("java/lang/Class" , "getDeclaredConstructors" , "()[Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getDeclaredConstructors ),
1389+
1390+ brk ("java/lang/Class" , "getMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getMethod ),
1391+ brk ("java/lang/Class" , "getConstructor" , "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructor ),
1392+ brk ("java/lang/Class" , "getDeclaredMethod" , "(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getDeclaredMethod ),
1393+ brk ("java/lang/Class" , "getDeclaredConstructor" , "([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getConstructor ),
1394+ };
1395+
13561396 private static BreakpointSpecification brk (String className , String methodName , String signature , BreakpointHandler handler ) {
13571397 return new BreakpointSpecification (className , methodName , signature , handler , false );
13581398 }
0 commit comments