62
62
import org .graalvm .nativeimage .hosted .FieldValueTransformer ;
63
63
64
64
import com .oracle .graal .pointsto .meta .AnalysisType ;
65
+ import com .oracle .svm .core .NativeImageClassLoaderOptions ;
65
66
import com .oracle .svm .core .SubstrateOptions ;
66
67
import com .oracle .svm .core .SubstrateUtil ;
67
68
import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
@@ -130,27 +131,26 @@ public final class ModuleLayerFeature implements InternalFeature {
130
131
public void duringSetup (DuringSetupAccess access ) {
131
132
FeatureImpl .DuringSetupAccessImpl accessImpl = (FeatureImpl .DuringSetupAccessImpl ) access ;
132
133
moduleLayerFeatureUtils = new ModuleLayerFeatureUtils (accessImpl .imageClassLoader );
133
-
134
- RuntimeModuleSupport .instance ().setHostedToRuntimeModuleMapper (moduleLayerFeatureUtils ::getOrCreateRuntimeModuleForHostedModule );
134
+ RuntimeModuleSupport .instance ().setHostedToRuntimeModuleMapper (m -> moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (m , accessImpl ));
135
135
136
136
/*
137
137
* Register an object replacer that will ensure all references to hosted module instances
138
138
* are replaced with the appropriate runtime module instance.
139
139
*/
140
- access .registerObjectReplacer (this :: replaceHostedModules );
140
+ access .registerObjectReplacer (source -> replaceHostedModules ( source , accessImpl ) );
141
141
}
142
142
143
- private Object replaceHostedModules (Object source ) {
143
+ private Object replaceHostedModules (Object source , AnalysisAccessBase access ) {
144
144
if (source instanceof Module module ) {
145
- return moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (module );
145
+ return moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (module , access );
146
146
} else if (source instanceof Class <?> clazz ) {
147
147
/*
148
148
* If the field Class(=DynamicHub).module is not reachable, we do not see all Module
149
149
* instances directly. So we also need to scan the module in Class/DynamicHub objects.
150
150
*/
151
- moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (clazz .getModule ());
151
+ moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (clazz .getModule (), access );
152
152
} else if (source instanceof DynamicHub hub ) {
153
- moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (hub .getModule ());
153
+ moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (hub .getModule (), access );
154
154
}
155
155
return source ;
156
156
}
@@ -451,7 +451,7 @@ private ModuleLayer synthesizeRuntimeModuleLayer(List<ModuleLayer> parentLayers,
451
451
runtimeModuleLayer = moduleLayerFeatureUtils .createNewModuleLayerInstance (runtimeModuleLayerConfiguration );
452
452
Map <String , Module > nameToModule = moduleLayerFeatureUtils .synthesizeNameToModule (accessImpl , runtimeModuleLayer , clf );
453
453
for (Module syntheticModule : syntheticModules ) {
454
- Module runtimeSyntheticModule = moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (syntheticModule );
454
+ Module runtimeSyntheticModule = moduleLayerFeatureUtils .getOrCreateRuntimeModuleForHostedModule (syntheticModule , accessImpl );
455
455
nameToModule .putIfAbsent (runtimeSyntheticModule .getName (), runtimeSyntheticModule );
456
456
moduleLayerFeatureUtils .patchModuleLayerField (accessImpl , runtimeSyntheticModule , runtimeModuleLayer );
457
457
}
@@ -538,8 +538,10 @@ private void replicateNativeAccess(AfterAnalysisAccessImpl accessImpl, Set<Modul
538
538
for (Map .Entry <Module , Module > modulesPair : modulePairs .entrySet ()) {
539
539
Module hosted = modulesPair .getKey ();
540
540
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
+ }
543
545
}
544
546
}
545
547
@@ -630,10 +632,14 @@ private static final class ModuleLayerFeatureUtils {
630
632
private final Field moduleLayerModulesField ;
631
633
private final Field moduleReferenceLocationField ;
632
634
private final Field moduleReferenceImplLocationField ;
635
+ private final Set <String > nativeAccessEnabled ;
633
636
634
637
ModuleLayerFeatureUtils (ImageClassLoader cl ) {
635
638
runtimeModules = new HashMap <>();
636
639
imageClassLoader = cl ;
640
+ nativeAccessEnabled = NativeImageClassLoaderOptions .EnableNativeAccess .getValue ().values ().stream ().flatMap (m -> Arrays .stream (SubstrateUtil .split (m , "," )))
641
+ .collect (Collectors .toSet ());
642
+
637
643
Method classGetDeclaredMethods0Method = ReflectionUtil .lookupMethod (Class .class , "getDeclaredFields0" , boolean .class );
638
644
try {
639
645
ModuleSupport .accessModuleByClass (ModuleSupport .Access .OPEN , ModuleLayerFeature .class , Module .class );
@@ -694,6 +700,15 @@ private static final class ModuleLayerFeatureUtils {
694
700
}
695
701
}
696
702
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
+
697
712
/**
698
713
* A manual field lookup is necessary due to reflection filters present in newer JDK
699
714
* versions. This method should be removed once {@link ReflectionUtil} becomes immune to
@@ -797,7 +812,7 @@ public Module getRuntimeModuleForHostedModule(ClassLoader loader, String hostedM
797
812
}
798
813
}
799
814
800
- public Module getOrCreateRuntimeModuleForHostedModule (Module hostedModule ) {
815
+ public Module getOrCreateRuntimeModuleForHostedModule (Module hostedModule , AnalysisAccessBase access ) {
801
816
/*
802
817
* Special module instances such as ALL_UNNAMED and EVERYONE_MODULE are not replicated
803
818
* as they only serve as marker modules (all their fields are null, including the loader
@@ -806,11 +821,13 @@ public Module getOrCreateRuntimeModuleForHostedModule(Module hostedModule) {
806
821
if (hostedModule == allUnnamedModule || hostedModule == everyoneModule ) {
807
822
return hostedModule ;
808
823
} 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 );
810
826
}
811
827
}
812
828
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 ) {
814
831
synchronized (runtimeModules ) {
815
832
Module runtimeModule = getRuntimeModuleForHostedModule (loader , hostedModuleName , true );
816
833
if (runtimeModule != null ) {
@@ -828,6 +845,9 @@ public Module getOrCreateRuntimeModuleForHostedModule(ClassLoader loader, String
828
845
}
829
846
runtimeModules .putIfAbsent (loader , new HashMap <>());
830
847
runtimeModules .get (loader ).put (hostedModuleName , runtimeModule );
848
+ if (enableNativeAccess ) {
849
+ enableNativeAccess (access , runtimeModule );
850
+ }
831
851
return runtimeModule ;
832
852
}
833
853
}
@@ -855,7 +875,8 @@ Map<String, Module> synthesizeNameToModule(AnalysisAccessBase access, ModuleLaye
855
875
ModuleDescriptor descriptor = mref .descriptor ();
856
876
String name = descriptor .name ();
857
877
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 );
859
880
if (!descriptor .equals (m .getDescriptor ())) {
860
881
moduleDescriptorField .set (m , descriptor );
861
882
access .rescanField (m , moduleDescriptorField );
@@ -1123,11 +1144,15 @@ boolean allowsNativeAccess(Module module) {
1123
1144
1124
1145
}
1125
1146
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" );
1127
1152
assert moduleEnableNativeAccessField != null : "Only available on JDK19+" ;
1128
1153
try {
1129
- moduleEnableNativeAccessField .set (module , value );
1130
- accessImpl .rescanField (module , moduleEnableNativeAccessField );
1154
+ moduleEnableNativeAccessField .set (module , true );
1155
+ access .rescanField (module , moduleEnableNativeAccessField );
1131
1156
} catch (IllegalAccessException e ) {
1132
1157
throw VMError .shouldNotReachHere ("Failed to reflectively set Module.enableNativeAccess." , e );
1133
1158
}
0 commit comments