From fa457cee9780d0e3abebfcf5c700a8729f1e8e6f Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Wed, 10 Sep 2025 12:21:28 +0200 Subject: [PATCH 1/2] Ignore missing registration errors when querying bundles from JavaUtilResourceBundleAccess --- .../Target_java_util_ResourceBundle.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java index f7696306ce6b..a7d69caf9641 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_java_util_ResourceBundle.java @@ -171,5 +171,20 @@ private static ResourceBundle getBundleFromModule(Class caller, private static native ClassLoader getLoader(Module module); @Alias - private static native ResourceBundle getBundleImpl(Module callerModule, Module module, String baseName, Locale locale, ResourceBundle.Control control); + static native ResourceBundle getBundleImpl(Module callerModule, Module module, String baseName, Locale locale, ResourceBundle.Control control); + + @Alias + static native Control getDefaultControl(Module targetModule, String baseName); +} + +@TargetClass(className = "java.util.ResourceBundle$1") +final class Target_java_util_ResourceBundle_1 { + @Substitute + @SuppressWarnings("static-method") + public ResourceBundle getBundle(String baseName, Locale locale, Module module) { + // use the given module as the caller to bypass the access check + return MissingRegistrationUtils.runIgnoringMissingRegistrations(() -> Target_java_util_ResourceBundle.getBundleImpl(module, module, + baseName, locale, + Target_java_util_ResourceBundle.getDefaultControl(module, baseName))); + } } From 590d5f8b8fc6ddf48d1c5d536ae89d2e07cccfeb Mon Sep 17 00:00:00 2001 From: Loic Ottet Date: Wed, 1 Oct 2025 17:03:30 +0200 Subject: [PATCH 2/2] Move AnnotationFeature documentation to class level --- .../svm/hosted/annotation/AnnotationFeature.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java index b0588883827a..cdd0002334d4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationFeature.java @@ -38,6 +38,14 @@ import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; import com.oracle.svm.hosted.reflect.ReflectionDataBuilder; +/** + * For annotations that are materialized at image run time, all necessary methods are registered for + * reflection in {@link ReflectionDataBuilder#registerTypesForAnnotation}. But if an annotation type + * is only used by an annotation that is already in the image heap, then we need to also register + * its methods for reflection. This is done here by registering a callback which notifies us for + * every reachable {@link Annotation} object in the heap and then checking if it is an annotation + * that was materialized by the JDK, i.e., it is a {@link Proxy}. + */ @AutomaticallyRegisteredFeature public class AnnotationFeature implements InternalFeature { @@ -49,14 +57,6 @@ public void duringSetup(DuringSetupAccess a) { access.registerObjectReachableCallback(Annotation.class, this::registerDeclaredMethods); } - /** - * For annotations that are materialized at image run time, all necessary methods are registered - * for reflection in {@link ReflectionDataBuilder#registerTypesForAnnotation}. But if an - * annotation type is only used by an annotation that is already in the image heap, then we need - * to also register its methods for reflection. This is done here by registering a callback - * which notifies us for every reachable {@link Annotation} object in the heap and then checking - * if it is an annotation that was materialized by the JDK, i.e., it is a {@link Proxy}. - */ @SuppressWarnings("unused") private void registerDeclaredMethods(DuringAnalysisAccess access, Annotation annotation, ObjectScanner.ScanReason reason) { if (Proxy.isProxyClass(annotation.getClass())) {