6262import org .graalvm .nativeimage .hosted .FieldValueTransformer ;
6363
6464import com .oracle .graal .pointsto .meta .AnalysisType ;
65+ import com .oracle .svm .core .NativeImageClassLoaderOptions ;
6566import com .oracle .svm .core .SubstrateOptions ;
6667import com .oracle .svm .core .SubstrateUtil ;
6768import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
@@ -130,27 +131,26 @@ public final class ModuleLayerFeature implements InternalFeature {
130131 public void duringSetup (DuringSetupAccess access ) {
131132 FeatureImpl .DuringSetupAccessImpl accessImpl = (FeatureImpl .DuringSetupAccessImpl ) access ;
132133 moduleLayerFeatureUtils = new ModuleLayerFeatureUtils (accessImpl .imageClassLoader );
133-
134- RuntimeModuleSupport .instance ().setHostedToRuntimeModuleMapper (moduleLayerFeatureUtils ::getOrCreateRuntimeModuleForHostedModule );
134+ RuntimeModuleSupport .instance ().setHostedToRuntimeModuleMapper (m -> moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (m , accessImpl ));
135135
136136 /*
137137 * Register an object replacer that will ensure all references to hosted module instances
138138 * are replaced with the appropriate runtime module instance.
139139 */
140- access .registerObjectReplacer (this :: replaceHostedModules );
140+ access .registerObjectReplacer (source -> replaceHostedModules ( source , accessImpl ) );
141141 }
142142
143- private Object replaceHostedModules (Object source ) {
143+ private Object replaceHostedModules (Object source , AnalysisAccessBase access ) {
144144 if (source instanceof Module module ) {
145- return moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (module );
145+ return moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (module , access );
146146 } else if (source instanceof Class <?> clazz ) {
147147 /*
148148 * If the field Class(=DynamicHub).module is not reachable, we do not see all Module
149149 * instances directly. So we also need to scan the module in Class/DynamicHub objects.
150150 */
151- moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (clazz .getModule ());
151+ moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (clazz .getModule (), access );
152152 } else if (source instanceof DynamicHub hub ) {
153- moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (hub .getModule ());
153+ moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (hub .getModule (), access );
154154 }
155155 return source ;
156156 }
@@ -451,7 +451,7 @@ private ModuleLayer synthesizeRuntimeModuleLayer(List<ModuleLayer> parentLayers,
451451 runtimeModuleLayer = moduleLayerFeatureUtils .createNewModuleLayerInstance (runtimeModuleLayerConfiguration );
452452 Map <String , Module > nameToModule = moduleLayerFeatureUtils .synthesizeNameToModule (accessImpl , runtimeModuleLayer , clf );
453453 for (Module syntheticModule : syntheticModules ) {
454- Module runtimeSyntheticModule = moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (syntheticModule );
454+ Module runtimeSyntheticModule = moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (syntheticModule , accessImpl );
455455 nameToModule .putIfAbsent (runtimeSyntheticModule .getName (), runtimeSyntheticModule );
456456 moduleLayerFeatureUtils .patchModuleLayerField (accessImpl , runtimeSyntheticModule , runtimeModuleLayer );
457457 }
@@ -538,8 +538,10 @@ private void replicateNativeAccess(AfterAnalysisAccessImpl accessImpl, Set<Modul
538538 for (Map .Entry <Module , Module > modulesPair : modulePairs .entrySet ()) {
539539 Module hosted = modulesPair .getKey ();
540540 Module runtime = modulesPair .getValue ();
541- if (moduleLayerFeatureUtils .allowsNativeAccess (hosted )) {
542- moduleLayerFeatureUtils .setNativeAccess (accessImpl , runtime , true );
541+ if (moduleLayerFeatureUtils .allowsNativeAccess (hosted ) || moduleLayerFeatureUtils .isNativeAccessEnabledForRuntimeModule (runtime )) {
542+ if (!moduleLayerFeatureUtils .allowsNativeAccess (runtime )) {
543+ moduleLayerFeatureUtils .enableNativeAccess (accessImpl , runtime );
544+ }
543545 }
544546 }
545547
@@ -630,10 +632,14 @@ private static final class ModuleLayerFeatureUtils {
630632 private final Field moduleLayerModulesField ;
631633 private final Field moduleReferenceLocationField ;
632634 private final Field moduleReferenceImplLocationField ;
635+ private final Set <String > nativeAccessEnabled ;
633636
634637 ModuleLayerFeatureUtils (ImageClassLoader cl ) {
635638 runtimeModules = new HashMap <>();
636639 imageClassLoader = cl ;
640+ nativeAccessEnabled = NativeImageClassLoaderOptions .EnableNativeAccess .getValue ().values ().stream ().flatMap (m -> Arrays .stream (SubstrateUtil .split (m , "," )))
641+ .collect (Collectors .toSet ());
642+
637643 Method classGetDeclaredMethods0Method = ReflectionUtil .lookupMethod (Class .class , "getDeclaredFields0" , boolean .class );
638644 try {
639645 ModuleSupport .accessModuleByClass (ModuleSupport .Access .OPEN , ModuleLayerFeature .class , Module .class );
@@ -694,6 +700,15 @@ private static final class ModuleLayerFeatureUtils {
694700 }
695701 }
696702
703+ private boolean isNativeAccessEnabledForRuntimeBootLayerModule (String runtimeModuleName ) {
704+ return nativeAccessEnabled .contains (runtimeModuleName );
705+ }
706+
707+ private boolean isNativeAccessEnabledForRuntimeModule (Module runtimeModule ) {
708+ String runtimeModuleName = runtimeModule .getName ();
709+ return RuntimeModuleSupport .instance ().getBootLayer () == runtimeModule .getLayer () && isNativeAccessEnabledForRuntimeBootLayerModule (runtimeModuleName );
710+ }
711+
697712 /**
698713 * A manual field lookup is necessary due to reflection filters present in newer JDK
699714 * versions. This method should be removed once {@link ReflectionUtil} becomes immune to
@@ -797,7 +812,7 @@ public Module getRuntimeModuleForHostedModule(ClassLoader loader, String hostedM
797812 }
798813 }
799814
800- public Module getOrCreateRuntimeModuleForHostedModule (Module hostedModule ) {
815+ public Module getOrCreateRuntimeModuleForHostedModule (Module hostedModule , AnalysisAccessBase access ) {
801816 /*
802817 * Special module instances such as ALL_UNNAMED and EVERYONE_MODULE are not replicated
803818 * as they only serve as marker modules (all their fields are null, including the loader
@@ -806,11 +821,13 @@ public Module getOrCreateRuntimeModuleForHostedModule(Module hostedModule) {
806821 if (hostedModule == allUnnamedModule || hostedModule == everyoneModule ) {
807822 return hostedModule ;
808823 } else {
809- return getOrCreateRuntimeModuleForHostedModule (hostedModule .getClassLoader (), hostedModule .getName (), hostedModule .getDescriptor ());
824+ boolean enableNativeAccess = allowsNativeAccess (hostedModule ) || isNativeAccessEnabledForRuntimeBootLayerModule (hostedModule .getName ());
825+ return getOrCreateRuntimeModuleForHostedModule (hostedModule .getClassLoader (), hostedModule .getName (), hostedModule .getDescriptor (), access , enableNativeAccess );
810826 }
811827 }
812828
813- public Module getOrCreateRuntimeModuleForHostedModule (ClassLoader loader , String hostedModuleName , ModuleDescriptor runtimeModuleDescriptor ) {
829+ public Module getOrCreateRuntimeModuleForHostedModule (ClassLoader loader , String hostedModuleName , ModuleDescriptor runtimeModuleDescriptor , AnalysisAccessBase access ,
830+ boolean enableNativeAccess ) {
814831 synchronized (runtimeModules ) {
815832 Module runtimeModule = getRuntimeModuleForHostedModule (loader , hostedModuleName , true );
816833 if (runtimeModule != null ) {
@@ -828,6 +845,9 @@ public Module getOrCreateRuntimeModuleForHostedModule(ClassLoader loader, String
828845 }
829846 runtimeModules .putIfAbsent (loader , new HashMap <>());
830847 runtimeModules .get (loader ).put (hostedModuleName , runtimeModule );
848+ if (enableNativeAccess ) {
849+ enableNativeAccess (access , runtimeModule );
850+ }
831851 return runtimeModule ;
832852 }
833853 }
@@ -855,7 +875,8 @@ Map<String, Module> synthesizeNameToModule(AnalysisAccessBase access, ModuleLaye
855875 ModuleDescriptor descriptor = mref .descriptor ();
856876 String name = descriptor .name ();
857877 ClassLoader loader = clf .apply (name );
858- Module m = getOrCreateRuntimeModuleForHostedModule (loader , name , descriptor );
878+ boolean nativeAccess = false ;
879+ Module m = getOrCreateRuntimeModuleForHostedModule (loader , name , descriptor , access , nativeAccess );
859880 if (!descriptor .equals (m .getDescriptor ())) {
860881 moduleDescriptorField .set (m , descriptor );
861882 access .rescanField (m , moduleDescriptorField );
@@ -1123,11 +1144,15 @@ boolean allowsNativeAccess(Module module) {
11231144
11241145 }
11251146
1126- void setNativeAccess (AfterAnalysisAccessImpl accessImpl , Module module , boolean value ) {
1147+ /**
1148+ * Allows the given module to perform native access.
1149+ */
1150+ void enableNativeAccess (AnalysisAccessBase access , Module module ) {
1151+ VMError .guarantee (!allowsNativeAccess (module ), "Cannot reset native access" );
11271152 assert moduleEnableNativeAccessField != null : "Only available on JDK19+" ;
11281153 try {
1129- moduleEnableNativeAccessField .set (module , value );
1130- accessImpl .rescanField (module , moduleEnableNativeAccessField );
1154+ moduleEnableNativeAccessField .set (module , true );
1155+ access .rescanField (module , moduleEnableNativeAccessField );
11311156 } catch (IllegalAccessException e ) {
11321157 throw VMError .shouldNotReachHere ("Failed to reflectively set Module.enableNativeAccess." , e );
11331158 }
0 commit comments