44
44
import com .oracle .svm .core .option .AccumulatingLocatableMultiOptionValue ;
45
45
import com .oracle .svm .core .option .HostedOptionKey ;
46
46
import com .oracle .svm .hosted .analysis .Inflation ;
47
+ import com .oracle .svm .hosted .substitute .AnnotationSubstitutionProcessor ;
48
+ import com .oracle .svm .hosted .substitute .DeletedMethod ;
47
49
48
50
import jdk .graal .compiler .options .Option ;
49
51
import jdk .graal .compiler .options .OptionType ;
52
+ import jdk .vm .ci .meta .MetaAccessProvider ;
50
53
51
54
/**
52
55
* Support for {@link ServiceLoader} on Substrate VM.
@@ -178,8 +181,14 @@ void handleServiceClassIsReachable(DuringAnalysisAccess access, Class<?> service
178
181
if (!accessImpl .getHostVM ().platformSupported (providerClass )) {
179
182
continue ;
180
183
}
181
- if (((Inflation ) accessImpl .getBigBang ()).getAnnotationSubstitutionProcessor ().isDeleted (providerClass )) {
182
- /* Disallow services with implementation classes that are marked as @Deleted */
184
+ AnnotationSubstitutionProcessor substitutionProcessor = ((Inflation ) accessImpl .getBigBang ()).getAnnotationSubstitutionProcessor ();
185
+ /*
186
+ * If ReportUnsupportedElementsAtRuntime is false, we can directly check the @Delete
187
+ * annotation on the substitute class. Otherwise, this check will return false even if
188
+ * providerClass is deleted. In such cases, the check, a couple of lines below, will
189
+ * handle the scenario.
190
+ */
191
+ if (substitutionProcessor .isDeleted (providerClass )) {
183
192
continue ;
184
193
}
185
194
@@ -189,32 +198,14 @@ void handleServiceClassIsReachable(DuringAnalysisAccess access, Class<?> service
189
198
*
190
199
* See ServiceLoader#loadProvider and ServiceLoader#findStaticProviderMethod.
191
200
*/
192
- Constructor <?> nullaryConstructor = null ;
193
- Method nullaryProviderMethod = null ;
194
- try {
195
- /* Only look for a provider() method if provider class is in an explicit module. */
196
- if (providerClass .getModule ().isNamed () && !providerClass .getModule ().getDescriptor ().isAutomatic ()) {
197
- for (Method method : providerClass .getDeclaredMethods ()) {
198
- if (Modifier .isPublic (method .getModifiers ()) && Modifier .isStatic (method .getModifiers ()) &&
199
- method .getParameterCount () == 0 && method .getName ().equals ("provider" )) {
200
- if (nullaryProviderMethod == null ) {
201
- nullaryProviderMethod = method ;
202
- } else {
203
- /* There must be at most one public static provider() method. */
204
- nullaryProviderMethod = null ;
205
- break ;
206
- }
207
- }
208
- }
209
- }
210
-
211
- Constructor <?> constructor = providerClass .getDeclaredConstructor ();
212
- if (Modifier .isPublic (constructor .getModifiers ())) {
213
- nullaryConstructor = constructor ;
214
- }
215
- } catch (NoSuchMethodException | SecurityException | LinkageError e ) {
216
- // ignore
201
+ Method nullaryProviderMethod = findProviderMethod (providerClass );
202
+ Constructor <?> nullaryConstructor = findNullaryConstructor (providerClass );
203
+ MetaAccessProvider originalMetaAccess = accessImpl .getBigBang ().getUniverse ().getOriginalMetaAccess ();
204
+ if (isServiceProviderDeleted (nullaryProviderMethod , nullaryConstructor , originalMetaAccess , substitutionProcessor )) {
205
+ /* Disallow services with implementation classes that are marked as @Deleted */
206
+ continue ;
217
207
}
208
+
218
209
if (nullaryConstructor != null || nullaryProviderMethod != null ) {
219
210
RuntimeReflection .register (providerClass );
220
211
if (nullaryConstructor != null ) {
@@ -258,4 +249,55 @@ void handleServiceClassIsReachable(DuringAnalysisAccess access, Class<?> service
258
249
RuntimeResourceAccess .addResource (access .getApplicationClassLoader ().getUnnamedModule (), serviceResourceLocation , serviceFileData );
259
250
}
260
251
}
252
+
253
+ private static Constructor <?> findNullaryConstructor (Class <?> providerClass ) {
254
+ Constructor <?> nullaryConstructor = null ;
255
+ try {
256
+ Constructor <?> constructor = providerClass .getDeclaredConstructor ();
257
+ if (Modifier .isPublic (constructor .getModifiers ())) {
258
+ nullaryConstructor = constructor ;
259
+ }
260
+ } catch (NoSuchMethodException | SecurityException | LinkageError e ) {
261
+ // ignore
262
+ }
263
+ return nullaryConstructor ;
264
+ }
265
+
266
+ private static Method findProviderMethod (Class <?> providerClass ) {
267
+ Method nullaryProviderMethod = null ;
268
+ try {
269
+ /* Only look for a provider() method if provider class is in an explicit module. */
270
+ if (providerClass .getModule ().isNamed () && !providerClass .getModule ().getDescriptor ().isAutomatic ()) {
271
+ for (Method method : providerClass .getDeclaredMethods ()) {
272
+ if (Modifier .isPublic (method .getModifiers ()) && Modifier .isStatic (method .getModifiers ()) &&
273
+ method .getParameterCount () == 0 && method .getName ().equals ("provider" )) {
274
+ if (nullaryProviderMethod == null ) {
275
+ nullaryProviderMethod = method ;
276
+ } else {
277
+ /* There must be at most one public static provider() method. */
278
+ nullaryProviderMethod = null ;
279
+ break ;
280
+ }
281
+ }
282
+ }
283
+ }
284
+
285
+ } catch (SecurityException | LinkageError e ) {
286
+ // ignore
287
+ }
288
+ return nullaryProviderMethod ;
289
+ }
290
+
291
+ private static boolean isServiceProviderDeleted (Method nullaryProviderMethod , Constructor <?> nullaryConstructor , MetaAccessProvider originalMetaAccess ,
292
+ AnnotationSubstitutionProcessor substitutionProcessor ) {
293
+ if (nullaryConstructor == null && nullaryProviderMethod == null ) {
294
+ /* In case when service provider is not JCA compliant. */
295
+ return false ;
296
+ }
297
+
298
+ boolean isNullaryConstructorDeletedOrNull = nullaryConstructor == null || substitutionProcessor .lookup (originalMetaAccess .lookupJavaMethod (nullaryConstructor )) instanceof DeletedMethod ;
299
+ boolean isNullaryProviderMethodDeletedOrNull = nullaryProviderMethod == null ||
300
+ substitutionProcessor .lookup (originalMetaAccess .lookupJavaMethod (nullaryProviderMethod )) instanceof DeletedMethod ;
301
+ return isNullaryConstructorDeletedOrNull && isNullaryProviderMethodDeletedOrNull ;
302
+ }
261
303
}
0 commit comments