@@ -136,6 +136,9 @@ final class BreakpointInterceptor {
136
136
/** Enables experimental support for class definitions via {@code ClassLoader.defineClass}. */
137
137
private static boolean experimentalClassDefineSupport = false ;
138
138
139
+ /** Enables tracking of reflection queries for fine-tuned configuration. */
140
+ private static boolean trackReflectionMetadata = false ;
141
+
139
142
/**
140
143
* Locations in methods where explicit calls to {@code ClassLoader.loadClass} have been found.
141
144
*/
@@ -367,6 +370,31 @@ private static boolean getEnclosingMethod(JNIEnvironment jni, Breakpoint bp, Int
367
370
return true ;
368
371
}
369
372
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
+
370
398
private static boolean newInstance (JNIEnvironment jni , Breakpoint bp , InterceptedState state ) {
371
399
JNIObjectHandle callerClass = state .getDirectCallerClass ();
372
400
JNIMethodId result = nullPointer ();
@@ -1068,12 +1096,13 @@ private static void onClassFileLoadHook(@SuppressWarnings("unused") JvmtiEnv jvm
1068
1096
1069
1097
public static void onLoad (JvmtiEnv jvmti , JvmtiEventCallbacks callbacks , Tracer writer , NativeImageAgent nativeImageTracingAgent ,
1070
1098
Supplier <InterceptedState > currentThreadJavaStackAccessSupplier ,
1071
- boolean exptlClassLoaderSupport , boolean exptlClassDefineSupport ) {
1099
+ boolean exptlClassLoaderSupport , boolean exptlClassDefineSupport , boolean trackReflectionData ) {
1072
1100
BreakpointInterceptor .tracer = writer ;
1073
1101
BreakpointInterceptor .agent = nativeImageTracingAgent ;
1074
1102
BreakpointInterceptor .interceptedStateSupplier = currentThreadJavaStackAccessSupplier ;
1075
1103
BreakpointInterceptor .experimentalClassLoaderSupport = exptlClassLoaderSupport ;
1076
1104
BreakpointInterceptor .experimentalClassDefineSupport = exptlClassDefineSupport ;
1105
+ BreakpointInterceptor .trackReflectionMetadata = trackReflectionData ;
1077
1106
1078
1107
JvmtiCapabilities capabilities = UnmanagedMemory .calloc (SizeOf .get (JvmtiCapabilities .class ));
1079
1108
check (jvmti .getFunctions ().GetCapabilities ().invoke (jvmti , capabilities ));
@@ -1122,7 +1151,13 @@ public static void onVMInit(JvmtiEnv jvmti, JNIEnvironment jni) {
1122
1151
1123
1152
JNIObjectHandle lastClass = nullHandle ();
1124
1153
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 ) {
1126
1161
JNIObjectHandle clazz = nullHandle ();
1127
1162
if (lastClassName != null && lastClassName .equals (br .className )) {
1128
1163
clazz = lastClass ;
@@ -1245,24 +1280,17 @@ private interface BreakpointHandler {
1245
1280
brk ("java/lang/Class" , "forName" , "(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;" , BreakpointInterceptor ::forName ),
1246
1281
1247
1282
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 ),
1250
1283
brk ("java/lang/Class" , "getClasses" , "()[Ljava/lang/Class;" , BreakpointInterceptor ::getClasses ),
1251
1284
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 ),
1254
1285
brk ("java/lang/Class" , "getDeclaredClasses" , "()[Ljava/lang/Class;" , BreakpointInterceptor ::getDeclaredClasses ),
1255
1286
1256
1287
brk ("java/lang/Class" , "getField" , "(Ljava/lang/String;)Ljava/lang/reflect/Field;" , BreakpointInterceptor ::getField ),
1257
1288
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 ),
1262
1289
1263
1290
brk ("java/lang/Class" , "getEnclosingMethod" , "()Ljava/lang/reflect/Method;" , BreakpointInterceptor ::getEnclosingMethod ),
1264
1291
brk ("java/lang/Class" , "getEnclosingConstructor" , "()Ljava/lang/reflect/Constructor;" , BreakpointInterceptor ::getEnclosingMethod ),
1265
1292
1293
+ brk ("java/lang/reflect/Method" , "invoke" , "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;" , BreakpointInterceptor ::invokeMethod ),
1266
1294
brk ("java/lang/Class" , "newInstance" , "()Ljava/lang/Object;" , BreakpointInterceptor ::newInstance ),
1267
1295
brk ("java/lang/reflect/Array" , "newInstance" , "(Ljava/lang/Class;I)Ljava/lang/Object;" , BreakpointInterceptor ::newArrayInstance ),
1268
1296
brk ("java/lang/reflect/Array" , "newInstance" , "(Ljava/lang/Class;[I)Ljava/lang/Object;" , BreakpointInterceptor ::newArrayInstanceMulti ),
@@ -1353,6 +1381,18 @@ private interface BreakpointHandler {
1353
1381
private static final BreakpointSpecification CLASSLOADER_LOAD_CLASS_BREAKPOINT_SPECIFICATION = optionalBrk ("java/lang/ClassLoader" , "loadClass" ,
1354
1382
"(Ljava/lang/String;)Ljava/lang/Class;" , BreakpointInterceptor ::loadClass );
1355
1383
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
+
1356
1396
private static BreakpointSpecification brk (String className , String methodName , String signature , BreakpointHandler handler ) {
1357
1397
return new BreakpointSpecification (className , methodName , signature , handler , false );
1358
1398
}
0 commit comments