Skip to content

Commit 25e8c9f

Browse files
committed
[GR-71117] [GR-71118] [GR-71119] Migrate SubstrateGraphBuilderPlugins, Jmx*Feature and ScalaFeature to JVMCI Reflection
PullRequest: graal/22506
2 parents b7e45d2 + 9ed4eaf commit 25e8c9f

File tree

7 files changed

+191
-89
lines changed

7 files changed

+191
-89
lines changed

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/FeatureImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,18 @@ public AnalysisMetaAccess getMetaAccess() {
243243
return bb.getMetaAccess();
244244
}
245245

246+
public AnalysisType findTypeByName(String className) {
247+
Class<?> clazz = findClassByName(className);
248+
if (clazz == null) {
249+
return null;
250+
}
251+
return getMetaAccess().lookupJavaType(clazz);
252+
}
253+
254+
public List<AnalysisType> findSubtypes(AnalysisType baseClass) {
255+
return imageClassLoader.findSubclasses(baseClass.getJavaClass(), false).stream().map(getMetaAccess()::lookupJavaType).toList();
256+
}
257+
246258
public boolean isReachable(Class<?> clazz) {
247259
return isReachable(getMetaAccess().lookupJavaType(clazz));
248260
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxClientFeature.java

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,17 @@
2525
*/
2626
package com.oracle.svm.hosted.jdk;
2727

28-
import org.graalvm.nativeimage.hosted.RuntimeJNIAccess;
29-
import org.graalvm.nativeimage.hosted.RuntimeReflection;
30-
28+
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
29+
import com.oracle.graal.pointsto.meta.AnalysisType;
3130
import com.oracle.svm.core.VMInspectionOptions;
3231
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3332
import com.oracle.svm.core.feature.InternalFeature;
3433
import com.oracle.svm.core.jdk.JNIRegistrationUtil;
3534
import com.oracle.svm.core.util.VMError;
36-
import com.oracle.svm.util.ReflectionUtil;
35+
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
36+
import com.oracle.svm.hosted.dynamicaccess.JVMCIRuntimeJNIAccess;
37+
import com.oracle.svm.hosted.dynamicaccess.JVMCIRuntimeReflection;
38+
import com.oracle.svm.util.JVMCIReflectionUtil;
3739

3840
@AutomaticallyRegisteredFeature
3941
public class JmxClientFeature extends JNIRegistrationUtil implements InternalFeature {
@@ -45,16 +47,19 @@ public boolean isInConfiguration(IsInConfigurationAccess access) {
4547
@Override
4648
public void beforeAnalysis(BeforeAnalysisAccess access) {
4749
try {
48-
configureJNI();
49-
configureReflection(access);
50+
BeforeAnalysisAccessImpl accessImpl = (BeforeAnalysisAccessImpl) access;
51+
configureJNI(accessImpl);
52+
configureReflection(accessImpl);
5053
} catch (Exception e) {
5154
throw VMError.shouldNotReachHere("ManagementClientFeature configuration failed: " + e);
5255
}
5356
}
5457

55-
private static void configureJNI() {
56-
RuntimeJNIAccess.register(Boolean.class);
57-
RuntimeJNIAccess.register(ReflectionUtil.lookupMethod(Boolean.class, "getBoolean", String.class));
58+
private static void configureJNI(BeforeAnalysisAccessImpl access) {
59+
AnalysisMetaAccess metaAccess = access.getMetaAccess();
60+
AnalysisType type = metaAccess.lookupJavaType(Boolean.class);
61+
JVMCIRuntimeJNIAccess.register(type);
62+
JVMCIRuntimeJNIAccess.register(JVMCIReflectionUtil.getDeclaredMethod(metaAccess, type, "getBoolean", String.class));
5863
}
5964

6065
/**
@@ -69,14 +74,14 @@ private static void configureJNI() {
6974
* {@code sun.rmi.server.UnicastRef#getRefClass(ObjectOutput)}.</li>
7075
* </ul>
7176
*/
72-
private static void configureReflection(BeforeAnalysisAccess access) {
73-
RuntimeReflection.register(access.findClassByName("com.sun.jndi.url.rmi.rmiURLContextFactory"));
74-
RuntimeReflection.register(access.findClassByName("sun.rmi.server.UnicastRef"));
77+
private static void configureReflection(BeforeAnalysisAccessImpl access) {
78+
JVMCIRuntimeReflection.register(access.findTypeByName("com.sun.jndi.url.rmi.rmiURLContextFactory"));
79+
JVMCIRuntimeReflection.register(access.findTypeByName("sun.rmi.server.UnicastRef"));
7580

76-
RuntimeReflection.register(access.findClassByName("com.sun.jmx.remote.protocol.rmi.ClientProvider"));
77-
RuntimeReflection.register(access.findClassByName("com.sun.jndi.url.rmi.rmiURLContextFactory").getConstructors());
78-
RuntimeReflection.register(access.findClassByName("sun.rmi.server.UnicastRef").getConstructors());
79-
RuntimeReflection.register(access.findClassByName("sun.rmi.server.UnicastRef2").getConstructors());
80-
RuntimeReflection.register(access.findClassByName("com.sun.jmx.remote.protocol.rmi.ClientProvider").getConstructors());
81+
JVMCIRuntimeReflection.register(access.findTypeByName("com.sun.jmx.remote.protocol.rmi.ClientProvider"));
82+
JVMCIRuntimeReflection.register(JVMCIReflectionUtil.getConstructors(access.findTypeByName("com.sun.jndi.url.rmi.rmiURLContextFactory")));
83+
JVMCIRuntimeReflection.register(JVMCIReflectionUtil.getConstructors(access.findTypeByName("sun.rmi.server.UnicastRef")));
84+
JVMCIRuntimeReflection.register(JVMCIReflectionUtil.getConstructors(access.findTypeByName("sun.rmi.server.UnicastRef2")));
85+
JVMCIRuntimeReflection.register(JVMCIReflectionUtil.getConstructors(access.findTypeByName("com.sun.jmx.remote.protocol.rmi.ClientProvider")));
8186
}
8287
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxCommonFeature.java

Lines changed: 60 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,20 @@
3030

3131
import org.graalvm.nativeimage.ImageSingletons;
3232
import org.graalvm.nativeimage.dynamicaccess.AccessCondition;
33-
import org.graalvm.nativeimage.hosted.RuntimeJNIAccess;
34-
import org.graalvm.nativeimage.hosted.RuntimeReflection;
3533
import org.graalvm.nativeimage.hosted.RuntimeSerialization;
3634

35+
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
3736
import com.oracle.svm.core.VMInspectionOptions;
3837
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3938
import com.oracle.svm.core.feature.InternalFeature;
39+
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
40+
import com.oracle.svm.hosted.dynamicaccess.JVMCIRuntimeJNIAccess;
41+
import com.oracle.svm.hosted.dynamicaccess.JVMCIRuntimeReflection;
4042
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;
41-
import com.oracle.svm.util.ReflectionUtil;
43+
import com.oracle.svm.util.JVMCIReflectionUtil;
44+
45+
import jdk.vm.ci.meta.ResolvedJavaMethod;
46+
import jdk.vm.ci.meta.ResolvedJavaType;
4247

4348
@AutomaticallyRegisteredFeature
4449
public class JmxCommonFeature implements InternalFeature {
@@ -125,10 +130,11 @@ public void afterRegistration(AfterRegistrationAccess access) {
125130

126131
@Override
127132
public void beforeAnalysis(BeforeAnalysisAccess access) {
128-
configureJNI();
129-
configureSerialization(access);
130-
configureReflection(access);
131-
configureProxy(access);
133+
BeforeAnalysisAccessImpl accessImpl = (BeforeAnalysisAccessImpl) access;
134+
configureJNI(accessImpl);
135+
configureSerialization(accessImpl);
136+
configureReflection(accessImpl);
137+
configureProxy(accessImpl);
132138
}
133139

134140
/**
@@ -156,7 +162,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
156162
* </ul>
157163
* </p>
158164
*/
159-
private static void configureProxy(BeforeAnalysisAccess access) {
165+
private static void configureProxy(BeforeAnalysisAccessImpl access) {
160166
ProxyRegistry proxyRegistry = ImageSingletons.lookup(ProxyRegistry.class);
161167
proxyRegistry.registerProxy(AccessCondition.unconditional(), false, access.findClassByName("com.sun.management.GarbageCollectorMXBean"),
162168
access.findClassByName("javax.management.NotificationEmitter"));
@@ -182,9 +188,11 @@ private static void configureProxy(BeforeAnalysisAccess access) {
182188
access.findClassByName("javax.management.NotificationEmitter"));
183189
}
184190

185-
private static void configureJNI() {
186-
RuntimeJNIAccess.register(Arrays.class);
187-
RuntimeJNIAccess.register(ReflectionUtil.lookupMethod(Arrays.class, "asList", Object[].class));
191+
private static void configureJNI(BeforeAnalysisAccessImpl access) {
192+
AnalysisMetaAccess metaAccess = access.getMetaAccess();
193+
ResolvedJavaType type = metaAccess.lookupJavaType(Arrays.class);
194+
JVMCIRuntimeJNIAccess.register(type);
195+
JVMCIRuntimeJNIAccess.register(JVMCIReflectionUtil.getDeclaredMethod(metaAccess, type, "asList", Object[].class));
188196
}
189197

190198
/**
@@ -202,7 +210,7 @@ private static void configureJNI() {
202210
* the remote JMX infrastructure (See {@code sun.management.MappedMXBeanType},
203211
* {@code com.sun.jmx.mbeanserver.MXBeanMapping#makeOpenClass(Type, javax.management.openmbean.OpenType)})
204212
*/
205-
private static void configureSerialization(BeforeAnalysisAccess access) {
213+
private static void configureSerialization(BeforeAnalysisAccessImpl access) {
206214
String[] classes = {
207215
"[B", "com.oracle.svm.core.jdk.UnsupportedFeatureError",
208216
"java.io.IOException", "java.lang.Boolean", "java.lang.ClassCastException", "java.lang.Error",
@@ -281,7 +289,7 @@ private static void configureSerialization(BeforeAnalysisAccess access) {
281289
* {@code javax.management.remote.rmi.RMIConnectionImpl_Stub}.</li>
282290
* </ul>
283291
*/
284-
private static void configureReflection(BeforeAnalysisAccess access) {
292+
private static void configureReflection(BeforeAnalysisAccessImpl access) {
285293
String[] classes = {
286294
"com.sun.management.internal.OperatingSystemImpl",
287295
"javax.management.remote.rmi.RMIConnectionImpl_Stub",
@@ -311,13 +319,49 @@ private static void configureReflection(BeforeAnalysisAccess access) {
311319
};
312320

313321
for (String clazz : classes) {
314-
RuntimeReflection.register(access.findClassByName(clazz));
322+
JVMCIRuntimeReflection.register(access.findTypeByName(clazz));
315323
}
316324
for (String clazz : methods) {
317-
RuntimeReflection.register(access.findClassByName(clazz).getMethods());
325+
registerMethods(access.findTypeByName(clazz));
318326
}
319327
for (String clazz : constructors) {
320-
RuntimeReflection.register(access.findClassByName(clazz).getConstructors());
328+
JVMCIRuntimeReflection.register(JVMCIReflectionUtil.getConstructors(access.findTypeByName(clazz)));
329+
}
330+
}
331+
332+
/**
333+
* Registers all public methods from the {@code declaringClass} and its super classes and
334+
* interfaces for runtime reflection.
335+
* <p>
336+
* Note: this code originally used {@link Class#getMethods()}, which has slightly different
337+
* semantics. For methods with the same signature, it only returns the most specific one. This
338+
* code registers all of them. This trades-off registering more methods than really needed for a
339+
* much simpler algorithm. Should at some point {@link JVMCIReflectionUtil} or
340+
* {@link ResolvedJavaType} get an implementation that behaves as {@link Class#getMethods()}, we
341+
* might want to use it.
342+
*/
343+
private static void registerMethods(ResolvedJavaType declaringClass) {
344+
if ("java.lang.Object".equals(declaringClass.toClassName())) {
345+
/*
346+
* Don't register java.lang.Object methods since those are not reflectively needed by
347+
* JMX. This a deviation from Class#getMethods().
348+
*/
349+
return;
350+
}
351+
// Start by fetching public declared methods...
352+
for (ResolvedJavaMethod m : declaringClass.getDeclaredMethods(false)) {
353+
if (m.isPublic()) {
354+
JVMCIRuntimeReflection.register(m);
355+
}
356+
}
357+
// ...then recur over superclass methods...
358+
ResolvedJavaType sc = declaringClass.getSuperclass();
359+
if (sc != null) {
360+
registerMethods(sc);
361+
}
362+
// ...and finally over direct superinterfaces.
363+
for (ResolvedJavaType intf : declaringClass.getInterfaces()) {
364+
registerMethods(intf);
321365
}
322366
}
323367
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JmxServerFeature.java

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
import org.graalvm.nativeimage.ImageSingletons;
3737
import org.graalvm.nativeimage.dynamicaccess.AccessCondition;
38-
import org.graalvm.nativeimage.hosted.RuntimeReflection;
3938

4039
import com.oracle.svm.configure.ResourcesRegistry;
4140
import com.oracle.svm.core.VMInspectionOptions;
@@ -46,8 +45,12 @@
4645
import com.oracle.svm.core.jdk.RuntimeSupport;
4746
import com.oracle.svm.core.jdk.management.ManagementAgentStartupHook;
4847
import com.oracle.svm.core.jdk.management.ManagementSupport;
49-
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;
5048
import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl;
49+
import com.oracle.svm.hosted.dynamicaccess.JVMCIRuntimeReflection;
50+
import com.oracle.svm.hosted.reflect.proxy.ProxyRegistry;
51+
import com.oracle.svm.util.JVMCIReflectionUtil;
52+
53+
import jdk.vm.ci.meta.ResolvedJavaType;
5154

5255
@AutomaticallyRegisteredFeature
5356
public class JmxServerFeature implements InternalFeature {
@@ -71,7 +74,7 @@ private static void handleNativeLibraries(BeforeAnalysisAccess access) {
7174
public void beforeAnalysis(BeforeAnalysisAccess access) {
7275
handleNativeLibraries(access);
7376
registerJMXAgentResources();
74-
configureReflection(access);
77+
configureReflection((BeforeAnalysisAccessImpl) access);
7578
configureProxy(access);
7679
RuntimeSupport.getRuntimeSupport().addStartupHook(new ManagementAgentStartupHook());
7780
}
@@ -107,20 +110,19 @@ private static void configureProxy(BeforeAnalysisAccess access) {
107110
* </li>
108111
* </ul>
109112
*/
110-
private static void configureReflection(BeforeAnalysisAccess access) {
113+
private static void configureReflection(BeforeAnalysisAccessImpl access) {
111114
Set<PlatformManagedObject> platformManagedObjects = ManagementSupport.getSingleton().getPlatformManagedObjects();
112115
for (PlatformManagedObject p : platformManagedObjects) {
113116
// The platformManagedObjects list contains some PlatformManagedObjectSupplier objects
114117
// that are meant to help initialize some MXBeans at runtime. Skip them here.
115118
if (p instanceof ManagementSupport.PlatformManagedObjectSupplier) {
116119
continue;
117120
}
118-
Class<?> clazz = p.getClass();
119-
RuntimeReflection.register(clazz);
121+
JVMCIRuntimeReflection.register(access.getMetaAccess().lookupJavaType(p.getClass()));
120122
}
121123

122-
Class<?> serviceProviderClass = access.findClassByName("com.sun.jmx.remote.protocol.rmi.ServerProvider");
123-
RuntimeReflection.register(serviceProviderClass);
124-
RuntimeReflection.register(serviceProviderClass.getConstructors());
124+
ResolvedJavaType serviceProviderClass = access.findTypeByName("com.sun.jmx.remote.protocol.rmi.ServerProvider");
125+
JVMCIRuntimeReflection.register(serviceProviderClass);
126+
JVMCIRuntimeReflection.register(JVMCIReflectionUtil.getConstructors(serviceProviderClass));
125127
}
126128
}

0 commit comments

Comments
 (0)