2424 */
2525package com .oracle .svm .hosted ;
2626
27- import java .lang .reflect .Constructor ;
28- import java .lang .reflect .Method ;
2927import java .lang .reflect .Modifier ;
3028import java .nio .charset .StandardCharsets ;
3129import java .util .Collection ;
4139import org .graalvm .nativeimage .hosted .RuntimeReflection ;
4240import org .graalvm .nativeimage .hosted .RuntimeResourceAccess ;
4341
42+ import com .oracle .graal .pointsto .constraints .UnsupportedPlatformException ;
4443import com .oracle .svm .core .FutureDefaultsOptions ;
4544import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
4645import com .oracle .svm .core .feature .InternalFeature ;
5049import com .oracle .svm .core .option .HostedOptionKey ;
5150import com .oracle .svm .core .util .BasedOnJDKFile ;
5251import com .oracle .svm .hosted .analysis .Inflation ;
52+ import com .oracle .svm .hosted .substitute .DeletedElementException ;
53+ import com .oracle .svm .util .JVMCIReflectionUtil ;
54+ import com .oracle .svm .util .dynamicaccess .JVMCIRuntimeReflection ;
5355
5456import jdk .graal .compiler .hotspot .CompilerConfigurationFactory ;
5557import jdk .graal .compiler .hotspot .HotSpotBackendFactory ;
5961import jdk .graal .compiler .options .OptionType ;
6062import jdk .graal .compiler .truffle .hotspot .TruffleCallBoundaryInstrumentationFactory ;
6163import jdk .vm .ci .hotspot .HotSpotJVMCIBackendFactory ;
64+ import jdk .vm .ci .meta .ResolvedJavaMethod ;
65+ import jdk .vm .ci .meta .ResolvedJavaType ;
6266import sun .util .locale .provider .LocaleDataMetaInfo ;
6367
6468/**
@@ -160,54 +164,75 @@ public void afterRegistration(AfterRegistrationAccess access) {
160164 public void beforeAnalysis (BeforeAnalysisAccess access ) {
161165 FeatureImpl .BeforeAnalysisAccessImpl accessImpl = (FeatureImpl .BeforeAnalysisAccessImpl ) access ;
162166 accessImpl .imageClassLoader .classLoaderSupport .serviceProvidersForEach ((serviceName , providers ) -> {
163- Class <?> serviceClass = access .findClassByName (serviceName );
164- boolean skipService = false ;
165- /* If the service should not end up in the image, we remove all the providers with it */
166167 Collection <String > providersToSkip = providers ;
167- if (servicesToSkip .contains (serviceName )) {
168- skipService = true ;
169- } else if (serviceClass == null || serviceClass .isArray () || serviceClass .isPrimitive ()) {
170- skipService = true ;
171- } else if (!accessImpl .getHostVM ().platformSupported (serviceClass )) {
172- skipService = true ;
173- } else {
174- providersToSkip = providers .stream ().filter (serviceProvidersToSkip ::contains ).collect (Collectors .toList ());
175- if (!providersToSkip .isEmpty ()) {
168+ try {
169+ /*
170+ * The following will throw an `UnsupportedPlatformException` if the service is not
171+ * supported.
172+ */
173+ ResolvedJavaType serviceClass = accessImpl .findTypeByName (serviceName );
174+ boolean skipService = false ;
175+ /*
176+ * If the service should not end up in the image, we remove all the providers with
177+ * it.
178+ */
179+ if (servicesToSkip .contains (serviceName )) {
176180 skipService = true ;
181+ } else if (serviceClass == null || serviceClass .isArray () || serviceClass .isPrimitive ()) {
182+ skipService = true ;
183+ } else if (!accessImpl .getHostVM ().platformSupported (serviceClass )) {
184+ skipService = true ;
185+ } else {
186+ providersToSkip = providers .stream ().filter (serviceProvidersToSkip ::contains ).collect (Collectors .toList ());
187+ if (!providersToSkip .isEmpty ()) {
188+ skipService = true ;
189+ }
177190 }
191+ if (!skipService ) {
192+ access .registerReachabilityHandler (a -> handleServiceClassIsReachable (a , serviceClass , providers ), serviceClass );
193+ return ;
194+ }
195+ } catch (UnsupportedPlatformException e ) {
196+ // Service class is not supported - skipping
178197 }
179- if (skipService ) {
180- ServiceCatalogSupport .singleton ().removeServicesFromServicesCatalog (serviceName , new HashSet <>(providersToSkip ));
181- return ;
182- }
183- access .registerReachabilityHandler (a -> handleServiceClassIsReachable (a , serviceClass , providers ), serviceClass );
198+ // skip service
199+ ServiceCatalogSupport .singleton ().removeServicesFromServicesCatalog (serviceName , new HashSet <>(providersToSkip ));
184200 });
185201 }
186202
187- void handleServiceClassIsReachable (DuringAnalysisAccess access , Class <?> serviceProvider , Collection <String > providers ) {
203+ void handleServiceClassIsReachable (DuringAnalysisAccess access , ResolvedJavaType serviceProvider , Collection <String > providers ) {
204+ FeatureImpl .DuringAnalysisAccessImpl accessImpl = (FeatureImpl .DuringAnalysisAccessImpl ) access ;
188205 LinkedHashSet <String > registeredProviders = new LinkedHashSet <>();
189206 for (String provider : providers ) {
190207 if (serviceProvidersToSkip .contains (provider )) {
191208 continue ;
192209 }
193- if (serviceProvider .equals (java .security .Provider .class ) && !SecurityProvidersSupport .singleton ().isUserRequestedSecurityProvider (provider )) {
210+ if (serviceProvider .equals (accessImpl . getMetaAccess (). lookupJavaType ( java .security .Provider .class ) ) && !SecurityProvidersSupport .singleton ().isUserRequestedSecurityProvider (provider )) {
194211 SecurityProvidersSupport .singleton ().markSecurityProviderAsNotLoaded (provider );
195212 } else {
196213 registerProviderForRuntimeReflectionAccess (access , provider , registeredProviders );
197214 }
198215 }
199- registerProviderForRuntimeResourceAccess (access .getApplicationClassLoader ().getUnnamedModule (), serviceProvider .getName (), registeredProviders );
216+ registerProviderForRuntimeResourceAccess (access .getApplicationClassLoader ().getUnnamedModule (), serviceProvider .toClassName (), registeredProviders );
200217 }
201218
202219 @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+21/src/java.base/share/classes/java/util/ServiceLoader.java#L745-L793" )
203220 public static void registerProviderForRuntimeReflectionAccess (DuringAnalysisAccess access , String provider , Set <String > registeredProviders ) {
221+ FeatureImpl .DuringAnalysisAccessImpl accessImpl = (FeatureImpl .DuringAnalysisAccessImpl ) access ;
204222 /* Make provider reflectively instantiable */
205- Class <?> providerClass = access .findClassByName (provider );
223+ ResolvedJavaType providerClass ;
224+ try {
225+ providerClass = accessImpl .findTypeByName (provider );
226+ } catch (UnsupportedPlatformException e ) {
227+ return ;
228+ } catch (DeletedElementException e ) {
229+ /* Disallow services with implementation classes that are marked as @Deleted */
230+ return ;
231+ }
206232
207233 if (providerClass == null || providerClass .isArray () || providerClass .isPrimitive ()) {
208234 return ;
209235 }
210- FeatureImpl .DuringAnalysisAccessImpl accessImpl = (FeatureImpl .DuringAnalysisAccessImpl ) access ;
211236 if (!accessImpl .getHostVM ().platformSupported (providerClass )) {
212237 return ;
213238 }
@@ -222,10 +247,10 @@ public static void registerProviderForRuntimeReflectionAccess(DuringAnalysisAcce
222247 *
223248 * See ServiceLoader#loadProvider and ServiceLoader#findStaticProviderMethod.
224249 */
225- Method nullaryProviderMethod = findProviderMethod (providerClass );
226- Constructor <?> nullaryConstructor = findNullaryConstructor (providerClass );
250+ ResolvedJavaMethod nullaryProviderMethod = findProviderMethod (providerClass );
251+ ResolvedJavaMethod nullaryConstructor = findNullaryConstructor (providerClass );
227252 if (nullaryConstructor != null || nullaryProviderMethod != null ) {
228- RuntimeReflection .register (providerClass );
253+ JVMCIRuntimeReflection .register (providerClass );
229254 if (nullaryConstructor != null ) {
230255 /*
231256 * Registering a constructor with
@@ -235,22 +260,22 @@ public static void registerProviderForRuntimeReflectionAccess(DuringAnalysisAcce
235260 * if-statement cannot be eliminated.
236261 *
237262 */
238- RuntimeReflection .register (nullaryConstructor );
263+ JVMCIRuntimeReflection .register (nullaryConstructor );
239264 } else {
240265 /*
241266 * If there's no nullary constructor, register it as negative lookup to avoid
242267 * throwing a MissingReflectionRegistrationError at run time.
243268 */
244- RuntimeReflection .registerConstructorLookup (providerClass );
269+ JVMCIRuntimeReflection .registerConstructorLookup (providerClass );
245270 }
246271 if (nullaryProviderMethod != null ) {
247- RuntimeReflection .register (nullaryProviderMethod );
272+ JVMCIRuntimeReflection .register (nullaryProviderMethod );
248273 } else {
249274 /*
250275 * If there's no declared public provider() method, register it as negative lookup
251276 * to avoid throwing a MissingReflectionRegistrationError at run time.
252277 */
253- RuntimeReflection .registerMethodLookup (providerClass , "provider" );
278+ JVMCIRuntimeReflection .registerMethodLookup (providerClass , "provider" );
254279 }
255280 }
256281 /*
@@ -270,28 +295,28 @@ public static void registerProviderForRuntimeResourceAccess(Module module, Strin
270295 }
271296
272297 @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+21/src/java.base/share/classes/java/util/ServiceLoader.java#L620-L631" )
273- private static Constructor <?> findNullaryConstructor (Class <?> providerClass ) {
274- Constructor <?> nullaryConstructor = null ;
298+ private static ResolvedJavaMethod findNullaryConstructor (ResolvedJavaType providerClass ) {
299+ ResolvedJavaMethod nullaryConstructor = null ;
275300 try {
276- Constructor <?> constructor = providerClass .getDeclaredConstructor ();
301+ ResolvedJavaMethod constructor = JVMCIReflectionUtil .getDeclaredConstructor (false , providerClass );
277302 if (Modifier .isPublic (constructor .getModifiers ())) {
278303 nullaryConstructor = constructor ;
279304 }
280- } catch (NoSuchMethodException | SecurityException | LinkageError e ) {
305+ } catch (SecurityException | LinkageError e ) {
281306 // ignore
282307 }
283308 return nullaryConstructor ;
284309 }
285310
286311 @ BasedOnJDKFile ("https://github.com/openjdk/jdk/blob/jdk-25+21/src/java.base/share/classes/java/util/ServiceLoader.java#L583-L612" )
287- private static Method findProviderMethod (Class <?> providerClass ) {
288- Method nullaryProviderMethod = null ;
312+ private static ResolvedJavaMethod findProviderMethod (ResolvedJavaType providerClass ) {
313+ ResolvedJavaMethod nullaryProviderMethod = null ;
289314 try {
290315 /* Only look for a provider() method if provider class is in an explicit module. */
291- if (providerClass .getModule ().isNamed () && !providerClass .getModule ().getDescriptor ().isAutomatic ()) {
292- for (Method method : providerClass .getDeclaredMethods ()) {
316+ if (JVMCIReflectionUtil .getModule (providerClass ).isNamed () && !JVMCIReflectionUtil .getModule (providerClass ).getDescriptor ().isAutomatic ()) {
317+ for (ResolvedJavaMethod method : providerClass .getDeclaredMethods (false )) {
293318 if (Modifier .isPublic (method .getModifiers ()) && Modifier .isStatic (method .getModifiers ()) &&
294- method .getParameterCount () == 0 && method .getName ().equals ("provider" )) {
319+ method .getSignature (). getParameterCount (false ) == 0 && method .getName ().equals ("provider" )) {
295320 if (nullaryProviderMethod == null ) {
296321 nullaryProviderMethod = method ;
297322 } else {
0 commit comments