Skip to content

Commit 646135b

Browse files
committed
svm: set native access for the image run time modules
1 parent 1be5637 commit 646135b

File tree

2 files changed

+74
-18
lines changed

2 files changed

+74
-18
lines changed

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ModuleLayerFeature.java

+42-17
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
import org.graalvm.nativeimage.hosted.FieldValueTransformer;
6363

6464
import com.oracle.graal.pointsto.meta.AnalysisType;
65+
import com.oracle.svm.core.NativeImageClassLoaderOptions;
6566
import com.oracle.svm.core.SubstrateOptions;
6667
import com.oracle.svm.core.SubstrateUtil;
6768
import 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
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageClassLoaderSupport.java

+32-1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
import java.util.stream.Collectors;
7676
import java.util.stream.Stream;
7777

78+
import com.oracle.svm.core.SubstrateUtil;
7879
import org.graalvm.collections.EconomicMap;
7980
import org.graalvm.collections.EconomicSet;
8081
import org.graalvm.collections.MapCursor;
@@ -379,7 +380,29 @@ private static void implAddReadsAllUnnamed(Module module) {
379380
implAddReadsAllUnnamed.setAccessible(true);
380381
implAddReadsAllUnnamed.invoke(module);
381382
} catch (ReflectiveOperationException | NoSuchElementException e) {
382-
VMError.shouldNotReachHere("Could reflectively call Module.implAddReadsAllUnnamed", e);
383+
VMError.shouldNotReachHere("Could not reflectively call Module.implAddReadsAllUnnamed", e);
384+
}
385+
}
386+
387+
static void implAddEnableNativeAccess(Module module) {
388+
try {
389+
Method implAddEnableNativeAccess = Module.class.getDeclaredMethod("implAddEnableNativeAccess");
390+
ModuleSupport.accessModuleByClass(ModuleSupport.Access.OPEN, NativeImageClassLoaderSupport.class, Module.class);
391+
implAddEnableNativeAccess.setAccessible(true);
392+
implAddEnableNativeAccess.invoke(module);
393+
} catch (ReflectiveOperationException | NoSuchElementException e) {
394+
VMError.shouldNotReachHere("Could not reflectively call Module.implAddEnableNativeAccess", e);
395+
}
396+
}
397+
398+
static void implAddEnableNativeAccessToAllUnnamed() {
399+
try {
400+
Method implAddEnableNativeAccess = Module.class.getDeclaredMethod("implAddEnableNativeAccessToAllUnnamed");
401+
ModuleSupport.accessModuleByClass(ModuleSupport.Access.OPEN, NativeImageClassLoaderSupport.class, Module.class);
402+
implAddEnableNativeAccess.setAccessible(true);
403+
implAddEnableNativeAccess.invoke(null);
404+
} catch (ReflectiveOperationException | NoSuchElementException e) {
405+
VMError.shouldNotReachHere("Could not reflectively call Module.implAddEnableNativeAccessToAllUnnamed", e);
383406
}
384407
}
385408

@@ -436,6 +459,14 @@ void processClassLoaderOptions() {
436459
}
437460
}
438461
});
462+
NativeImageClassLoaderOptions.EnableNativeAccess.getValue(parsedHostedOptions).values().stream().flatMap(m -> Arrays.stream(SubstrateUtil.split(m, ","))).forEach(moduleName -> {
463+
if ("ALL-UNNAMED".equals(moduleName)) {
464+
implAddEnableNativeAccessToAllUnnamed();
465+
} else {
466+
Module module = findModule(moduleName).orElseThrow(() -> userWarningModuleNotFound(NativeImageClassLoaderOptions.EnableNativeAccess, moduleName));
467+
implAddEnableNativeAccess(module);
468+
}
469+
});
439470
}
440471

441472
private static void warn(String m) {

0 commit comments

Comments
 (0)