Skip to content

Commit d9d5007

Browse files
committed
WIP
1 parent 7e6c2bb commit d9d5007

File tree

24 files changed

+766
-149
lines changed

24 files changed

+766
-149
lines changed

sdk/src/org.graalvm.nativeimage/src/org/graalvm/nativeimage/impl/ReflectionRegistry.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,8 @@ public interface ReflectionRegistry {
5050

5151
void register(boolean finalIsWritable, Field... fields);
5252

53+
@SuppressWarnings("unused")
54+
default void registerAsQueried(Executable... methods) {
55+
// TODO unimplemented/shouldNotReachHere?
56+
}
5357
}

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/BreakpointInterceptor.java

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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
}

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
121121
boolean configurationWithOrigins = false;
122122
int configWritePeriod = -1; // in seconds
123123
int configWritePeriodInitialDelay = 1; // in seconds
124+
boolean trackReflectionMetadata = false;
124125

125126
String[] tokens = !options.isEmpty() ? options.split(",") : new String[0];
126127
for (String token : tokens) {
@@ -189,6 +190,8 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
189190
build = Boolean.parseBoolean(getTokenValue(token));
190191
} else if (token.equals("experimental-configuration-with-origins")) {
191192
configurationWithOrigins = true;
193+
} else if (token.equals("track-reflection-metadata")) {
194+
trackReflectionMetadata = true;
192195
} else {
193196
return usage(1, "unknown option: '" + token + "'.");
194197
}
@@ -306,7 +309,8 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
306309
}
307310

308311
try {
309-
BreakpointInterceptor.onLoad(jvmti, callbacks, tracer, this, interceptedStateSupplier, experimentalClassLoaderSupport, experimentalClassDefineSupport);
312+
BreakpointInterceptor.onLoad(jvmti, callbacks, tracer, this, interceptedStateSupplier,
313+
experimentalClassLoaderSupport, experimentalClassDefineSupport, trackReflectionMetadata);
310314
} catch (Throwable t) {
311315
return error(3, t.toString());
312316
}

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgentJNIHandleSet.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public class NativeImageAgentJNIHandleSet extends JNIHandleSet {
4242

4343
final JNIMethodId javaLangReflectMemberGetName;
4444
final JNIMethodId javaLangReflectMemberGetDeclaringClass;
45+
final JNIMethodId javaLangReflectMethodGetParameterTypes;
4546

4647
final JNIMethodId javaUtilEnumerationHasMoreElements;
4748

@@ -76,8 +77,10 @@ public class NativeImageAgentJNIHandleSet extends JNIHandleSet {
7677
javaLangClassGetName = getMethodId(env, javaLangClass, "getName", "()Ljava/lang/String;", false);
7778

7879
JNIObjectHandle javaLangReflectMember = findClass(env, "java/lang/reflect/Member");
80+
JNIObjectHandle javaLangReflectMethod = findClass(env, "java/lang/reflect/Method");
7981
javaLangReflectMemberGetName = getMethodId(env, javaLangReflectMember, "getName", "()Ljava/lang/String;", false);
8082
javaLangReflectMemberGetDeclaringClass = getMethodId(env, javaLangReflectMember, "getDeclaringClass", "()Ljava/lang/Class;", false);
83+
javaLangReflectMethodGetParameterTypes = getMethodId(env, javaLangReflectMethod, "getParameterTypes", "()[Ljava/lang/Class;", false);
8184

8285
JNIObjectHandle javaUtilEnumeration = findClass(env, "java/util/Enumeration");
8386
javaUtilEnumerationHasMoreElements = getMethodId(env, javaUtilEnumeration, "hasMoreElements", "()Z", false);

0 commit comments

Comments
 (0)