3030
3131import org .graalvm .nativeimage .ImageSingletons ;
3232import org .graalvm .nativeimage .dynamicaccess .AccessCondition ;
33- import org .graalvm .nativeimage .hosted .RuntimeJNIAccess ;
34- import org .graalvm .nativeimage .hosted .RuntimeReflection ;
3533import org .graalvm .nativeimage .hosted .RuntimeSerialization ;
3634
35+ import com .oracle .graal .pointsto .meta .AnalysisMetaAccess ;
3736import com .oracle .svm .core .VMInspectionOptions ;
3837import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
3938import 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 ;
4042import 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
4449public 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}
0 commit comments