diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java index 8453ecb2db1d..becf945b942d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java @@ -143,7 +143,7 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o @Option(help = "Allow MethodTypeFlow to see @Fold methods")// public static final HostedOptionKey AllowFoldMethods = new HostedOptionKey<>(false); - @APIOption(name = "report-unsupported-elements-at-runtime", deprecated = "The flag is not needed anymore as usage of unsupported elements is now reported at run time by default.")// + @APIOption(name = "report-unsupported-elements-at-runtime", deprecated = "The option is deprecated and will be removed in the future. The use of unsupported elements is always reported at run time.")// @Option(help = "Report usage of unsupported methods and fields at run time when they are accessed the first time, instead of as an error during image building", type = Debug)// public static final HostedOptionKey ReportUnsupportedElementsAtRuntime = new HostedOptionKey<>(true); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java index 29f9d731b83f..507ca45ea482 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AnnotationSubstitutionProcessor.java @@ -585,23 +585,35 @@ private static boolean hasDefaultValue(Field annotatedField) { private void handleDeletedClass(Class originalClass, Delete deleteAnnotation) { if (NativeImageOptions.ReportUnsupportedElementsAtRuntime.getValue()) { + ResolvedJavaType type = metaAccess.lookupJavaType(originalClass); + + try { + type.link(); + } catch (LinkageError ignored) { + /* + * Ignore any linking errors. A type that cannot be linked doesn't need elements + * replaced: it will simply fail at runtime with the same linkage error before + * reaching those elements. + */ + return; + } + /* * We register all methods and fields as deleted. That still allows usage of the type in * type checks. */ - for (Executable m : originalClass.getDeclaredMethods()) { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); + for (ResolvedJavaMethod method : type.getDeclaredMethods()) { registerAsDeleted(null, method, deleteAnnotation); } - for (Executable m : originalClass.getDeclaredConstructors()) { - ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m); - registerAsDeleted(null, method, deleteAnnotation); + for (ResolvedJavaMethod constructor : type.getDeclaredConstructors()) { + registerAsDeleted(null, constructor, deleteAnnotation); } - for (Field f : originalClass.getDeclaredFields()) { - ResolvedJavaField field = metaAccess.lookupJavaField(f); - registerAsDeleted(null, field, deleteAnnotation); + for (ResolvedJavaField f : type.getInstanceFields(false)) { + registerAsDeleted(null, f, deleteAnnotation); + } + for (ResolvedJavaField f : type.getStaticFields()) { + registerAsDeleted(null, f, deleteAnnotation); } - } else { deleteAnnotations.put(metaAccess.lookupJavaType(originalClass), deleteAnnotation); }