From 29a07210466bcc235ece2219ad5be44784ebc7f1 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 4 Nov 2021 16:31:08 +0100 Subject: [PATCH 01/16] Reset Module.ReflectionData maps; Remove ad-hoc fix for ResourceBundles --- .../Target_java_lang_Module_JDK11OrLater.java | 22 +++++++---------- .../oracle/svm/hosted/ModuleLayerFeature.java | 24 +++++++++---------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_Module_JDK11OrLater.java b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_Module_JDK11OrLater.java index 5c9ba0cadd97..d4f19b46db79 100644 --- a/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_Module_JDK11OrLater.java +++ b/substratevm/src/com.oracle.svm.core.jdk11/src/com/oracle/svm/core/jdk11/Target_java_lang_Module_JDK11OrLater.java @@ -24,6 +24,12 @@ */ package com.oracle.svm.core.jdk11; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.util.Arrays; +import java.util.Map; +import java.util.Objects; + import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.annotate.Substitute; @@ -34,23 +40,10 @@ import com.oracle.svm.core.jdk.Resources; import com.oracle.svm.core.jdk.resources.ResourceStorageEntry; -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Arrays; -import java.util.Map; -import java.util.Objects; - @SuppressWarnings("unused") @TargetClass(value = java.lang.Module.class, onlyWith = JDK11OrLater.class) public final class Target_java_lang_Module_JDK11OrLater { - @SuppressWarnings({"unused", "static-method"}) - @Substitute - public boolean isReflectivelyExportedOrOpen(String pn, Module other, boolean open) { - // This workaround should be removed once GR-34444 is fixed. - return true; - } - @SuppressWarnings("static-method") @Substitute public InputStream getResourceAsStream(String name) { @@ -97,10 +90,13 @@ private static void addExportsToAllUnnamed0(Module from, String pn) { @TargetClass(className = "java.lang.Module", innerClass = "ReflectionData", onlyWith = JDK11OrLater.class) // private static final class Target_java_lang_Module_ReflectionData { + @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "java.lang.WeakPairMap") // static Target_java_lang_WeakPairMap reads; + @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "java.lang.WeakPairMap") // static Target_java_lang_WeakPairMap> exports; + @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "java.lang.WeakPairMap") // static Target_java_lang_WeakPairMap, Boolean> uses; } diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 3f0c27bec9d0..58359f37a79a 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -24,18 +24,6 @@ */ package com.oracle.svm.hosted; -import com.oracle.graal.pointsto.meta.AnalysisUniverse; -import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.jdk11.BootModuleLayerSupport; -import com.oracle.svm.core.jdk.JDK11OrLater; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.util.ModuleSupport; -import com.oracle.svm.util.ReflectionUtil; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.hosted.Feature; - import java.lang.module.Configuration; import java.lang.module.FindException; import java.lang.module.ModuleDescriptor; @@ -61,6 +49,18 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.jdk11.BootModuleLayerSupport; +import com.oracle.svm.core.jdk.JDK11OrLater; +import com.oracle.svm.core.util.VMError; +import com.oracle.svm.util.ModuleSupport; +import com.oracle.svm.util.ReflectionUtil; +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.nativeimage.hosted.Feature; + /** * This feature: *
    From a4b806b5f35d8e9e1f70897c0c113915de3d77c0 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 4 Nov 2021 16:31:50 +0100 Subject: [PATCH 02/16] Transfer hosted module graph modifications to runtime boot module layer --- .../oracle/svm/hosted/ModuleLayerFeature.java | 170 +++++++++++++++++- 1 file changed, 161 insertions(+), 9 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 58359f37a79a..3b25c073e3a4 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -97,7 +97,7 @@ public final class ModuleLayerFeature implements Feature { private Constructor moduleLayerConstructor; private Field moduleLayerNameToModuleField; private Field moduleLayerParentsField; - private NameToModuleSynthesizer nameToModuleSynthesizer; + private ModuleLayerFeatureUtils moduleLayerFeatureUtils; @Override public boolean isInConfiguration(IsInConfigurationAccess access) { @@ -110,7 +110,7 @@ public void afterRegistration(AfterRegistrationAccess access) { moduleLayerConstructor = ReflectionUtil.lookupConstructor(ModuleLayer.class, Configuration.class, List.class, Function.class); moduleLayerNameToModuleField = ReflectionUtil.lookupField(ModuleLayer.class, "nameToModule"); moduleLayerParentsField = ReflectionUtil.lookupField(ModuleLayer.class, "parents"); - nameToModuleSynthesizer = new NameToModuleSynthesizer(); + moduleLayerFeatureUtils = new ModuleLayerFeatureUtils(); } @Override @@ -135,14 +135,20 @@ public void afterAnalysis(AfterAnalysisAccess access) { .map(t -> t.getJavaClass().getModule()) .distinct(); - Set allReachableModules = analysisReachableModules + Set analysisReachableNamedModules = analysisReachableModules .filter(Module::isNamed) .filter(m -> !m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) + .collect(Collectors.toSet()); + + Set allReachableModules = analysisReachableNamedModules + .stream() .flatMap(ModuleLayerFeature::extractRequiredModuleNames) .collect(Collectors.toSet()); ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, allReachableModules); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); + + replicateVisibilityModifications(runtimeBootLayer, accessImpl.imageClassLoader, analysisReachableNamedModules); } /* @@ -157,7 +163,7 @@ private ModuleLayer synthesizeRuntimeBootLayer(ImageClassLoader cl, Set Configuration cf = synthesizeRuntimeBootLayerConfiguration(cl.modulepath(), reachableModules); try { ModuleLayer runtimeBootLayer = moduleLayerConstructor.newInstance(cf, List.of(), null); - Map nameToModule = nameToModuleSynthesizer.synthesizeNameToModule(runtimeBootLayer, cl.getClassLoader()); + Map nameToModule = moduleLayerFeatureUtils.synthesizeNameToModule(runtimeBootLayer, cl.getClassLoader()); patchRuntimeBootLayer(runtimeBootLayer, nameToModule); return runtimeBootLayer; } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) { @@ -165,6 +171,71 @@ private ModuleLayer synthesizeRuntimeBootLayer(ImageClassLoader cl, Set } } + private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, ImageClassLoader cl, Set analysisReachableModules) { + List applicationModules = findApplicationModules(runtimeBootLayer, cl.applicationModulePath()); + + Map moduleLookupMap = analysisReachableModules + .stream() + .collect(Collectors.toMap(Module::getName, m -> new HostedRuntimeModulePair(m, runtimeBootLayer))); + + Module builderModule = moduleLookupMap.get("org.graalvm.nativeimage.builder").hostedModule; + assert builderModule != null; + + try { + for (Map.Entry e : moduleLookupMap.entrySet()) { + Module hostedModule = e.getValue().hostedModule; + if (hostedModule == builderModule) { + continue; + } + Module runtimeModule = e.getValue().runtimeModule; + if (builderModule.canRead(hostedModule)) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addReads(appModule, runtimeModule); + } + } + for (String pn : hostedModule.getPackages()) { + if (hostedModule.isOpen(pn, builderModule)) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addOpens(runtimeModule, pn, appModule); + } + } + if (hostedModule.isExported(pn, builderModule)) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addExports(runtimeModule, pn, appModule); + } + } + } + } + } catch (IllegalAccessException ex) { + throw VMError.shouldNotReachHere("Failed to transfer hosted module relations to the runtime boot module layer.", ex); + } + } + + private List findApplicationModules(ModuleLayer runtimeBootLayer, List applicationModulePath) { + List applicationModules = new ArrayList<>(); + List applicationModuleNames; + try { + ModuleFinder applicationModuleFinder = ModuleFinder.of(applicationModulePath.toArray(Path[]::new)); + applicationModuleNames = applicationModuleFinder.findAll() + .stream() + .map(m -> m.descriptor().name()) + .filter(s -> !s.startsWith("org.graal")) + .collect(Collectors.toList()); + } catch (FindException | ResolutionException | SecurityException ex) { + throw VMError.shouldNotReachHere("Failed to locate application modules.", ex); + } + + for (String moduleName : applicationModuleNames) { + Optional module = runtimeBootLayer.findModule(moduleName); + if (module.isEmpty()) { + throw VMError.shouldNotReachHere("Runtime boot module layer failed to include application module: " + moduleName); + } + applicationModules.add(module.get()); + } + + return applicationModules; + } + private static Configuration synthesizeRuntimeBootLayerConfiguration(List mp, Set reachableModules) { ModuleFinder beforeFinder = new BootModuleLayerModuleFinder(); ModuleFinder afterFinder = ModuleFinder.of(mp.toArray(Path[]::new)); @@ -219,7 +290,19 @@ public Set findAll() { } } - private static final class NameToModuleSynthesizer { + private static final class HostedRuntimeModulePair { + final Module hostedModule; + final Module runtimeModule; + + HostedRuntimeModulePair(Module hostedModule, ModuleLayer runtimeBootLayer) { + this.hostedModule = hostedModule; + this.runtimeModule = runtimeBootLayer.findModule(hostedModule.getName()).orElseThrow(VMError::shouldNotReachHere); + } + } + + private static final class ModuleLayerFeatureUtils { + private final Module allUnnamedModule; + private final Set allUnnamedModuleSet; private final Module everyoneModule; private final Set everyoneSet; private final Constructor moduleConstructor; @@ -229,7 +312,7 @@ private static final class NameToModuleSynthesizer { private final Field moduleExportedPackagesField; private final Method moduleFindModuleMethod; - NameToModuleSynthesizer() { + ModuleLayerFeatureUtils() { Method classGetDeclaredMethods0Method = ReflectionUtil.lookupMethod(Class.class, "getDeclaredFields0", boolean.class); try { ModuleSupport.openModuleByClass(Module.class, ModuleLayerFeature.class); @@ -239,6 +322,10 @@ private static final class NameToModuleSynthesizer { everyoneModuleField.setAccessible(true); everyoneModule = (Module) everyoneModuleField.get(null); + Field allUnnamedModuleField = findFieldByName(moduleClassFields, "ALL_UNNAMED_MODULE"); + allUnnamedModuleField.setAccessible(true); + allUnnamedModule = (Module) allUnnamedModuleField.get(null); + moduleLayerField = findFieldByName(moduleClassFields, "layer"); moduleReadsField = findFieldByName(moduleClassFields, "reads"); moduleOpenPackagesField = findFieldByName(moduleClassFields, "openPackages"); @@ -248,15 +335,18 @@ private static final class NameToModuleSynthesizer { moduleOpenPackagesField.setAccessible(true); moduleExportedPackagesField.setAccessible(true); } catch (ReflectiveOperationException | NoSuchElementException ex) { - throw VMError.shouldNotReachHere("Failed to find the value of EVERYONE_MODULE field of Module class.", ex); + throw VMError.shouldNotReachHere("Failed to retrieve fields of the Module class.", ex); } - everyoneSet = Set.of(everyoneModule); + allUnnamedModuleSet = new HashSet<>(); + allUnnamedModuleSet.add(allUnnamedModule); + everyoneSet = new HashSet<>(); + everyoneSet.add(everyoneModule); moduleConstructor = ReflectionUtil.lookupConstructor(Module.class, ClassLoader.class, ModuleDescriptor.class); moduleFindModuleMethod = ReflectionUtil.lookupMethod(Module.class, "findModule", String.class, Map.class, Map.class, List.class); } private static Field findFieldByName(Field[] fields, String name) { - return Arrays.stream(fields).filter(f -> f.getName().equals(name)).findAny().get(); + return Arrays.stream(fields).filter(f -> f.getName().equals(name)).findAny().orElseThrow(VMError::shouldNotReachHere); } /** @@ -380,5 +470,67 @@ Map synthesizeNameToModule(ModuleLayer runtimeBootLayer, ClassLo return nameToModule; } + + @SuppressWarnings("unchecked") + void addReads(Module module, Module other) throws IllegalAccessException { + Set reads = (Set) moduleReadsField.get(module); + if (reads == null) { + reads = new HashSet<>(); + moduleReadsField.set(module, reads); + } + reads.add(other == null ? allUnnamedModule : other); + } + + @SuppressWarnings("unchecked") + void addExports(Module module, String pn, Module other) throws IllegalAccessException { + if (other != null && module.isExported(pn, other)) { + return; + } + + Map> exports = (Map>) moduleExportedPackagesField.get(module); + if (exports == null) { + exports = new HashMap<>(); + moduleExportedPackagesField.set(module, exports); + } + + Set prev; + if (other == null) { + prev = exports.putIfAbsent(pn, allUnnamedModuleSet); + } else { + HashSet targets = new HashSet<>(); + targets.add(other); + prev = exports.putIfAbsent(pn, targets); + } + + if (prev != null) { + prev.add(other == null ? allUnnamedModule : other); + } + } + + @SuppressWarnings("unchecked") + void addOpens(Module module, String pn, Module other) throws IllegalAccessException { + if (other != null && module.isOpen(pn, other)) { + return; + } + + Map> opens = (Map>) moduleOpenPackagesField.get(module); + if (opens == null) { + opens = new HashMap<>(); + moduleOpenPackagesField.set(module, opens); + } + + Set prev; + if (other == null) { + prev = opens.putIfAbsent(pn, allUnnamedModuleSet); + } else { + HashSet targets = new HashSet<>(); + targets.add(other); + prev = opens.putIfAbsent(pn, targets); + } + + if (prev != null) { + prev.add(other == null ? allUnnamedModule : other); + } + } } } From 6a307af7b23b10ebb033b3cbbdad06807834f7aa Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 4 Nov 2021 16:34:25 +0100 Subject: [PATCH 03/16] Patch dynamic hubs to point to synthesized Module instances --- .../oracle/svm/hosted/ModuleLayerFeature.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 3b25c073e3a4..281e515eeebf 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -49,8 +49,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.svm.core.annotate.AutomaticFeature; +import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jdk11.BootModuleLayerSupport; import com.oracle.svm.core.jdk.JDK11OrLater; import com.oracle.svm.core.util.VMError; @@ -149,6 +151,29 @@ public void afterAnalysis(AfterAnalysisAccess access) { BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); replicateVisibilityModifications(runtimeBootLayer, accessImpl.imageClassLoader, analysisReachableNamedModules); + patchDynamicHubs(universe.getTypes(), accessImpl.bb.getHostVM(), runtimeBootLayer); + } + + /* + * Updates module fields of all DynamicHubs with appropriate synthesized module instances + */ + private void patchDynamicHubs(List types, SVMHost host, ModuleLayer runtimeBootLayer) { + for (AnalysisType type : types) { + if (!type.isReachable() || type.isArray()) { + continue; + } + Class clazz = type.getJavaClass(); + if (clazz.getModule().getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) { + continue; + } + DynamicHub hub = host.dynamicHub(type); + String moduleName = clazz.getModule().getName(); + Optional module = runtimeBootLayer.findModule(moduleName); + if (module.isEmpty()) { + throw VMError.shouldNotReachHere("Runtime boot module layer failed to include reachable module: " + moduleName); + } + hub.setModule(module.get()); + } } /* From 1a26eb6b3f04a37ca1c6d800049926dc30d5863d Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 4 Nov 2021 22:25:45 +0100 Subject: [PATCH 04/16] Include librarysupport module in boot layer --- .../src/com/oracle/svm/hosted/ModuleLayerFeature.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 281e515eeebf..f272e6082152 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -146,6 +146,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { .stream() .flatMap(ModuleLayerFeature::extractRequiredModuleNames) .collect(Collectors.toSet()); + allReachableModules.add("org.graalvm.nativeimage.librarysupport"); ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, allReachableModules); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); @@ -244,7 +245,6 @@ private List findApplicationModules(ModuleLayer runtimeBootLayer, List

    m.descriptor().name()) - .filter(s -> !s.startsWith("org.graal")) .collect(Collectors.toList()); } catch (FindException | ResolutionException | SecurityException ex) { throw VMError.shouldNotReachHere("Failed to locate application modules.", ex); From 68d2936a5f6d1c79f6f163925ee7839424c70ef5 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Fri, 5 Nov 2021 14:33:24 +0100 Subject: [PATCH 05/16] Ignore application modules that are not reachable --- .../src/com/oracle/svm/hosted/ModuleLayerFeature.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index f272e6082152..28b0bbce9369 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -146,7 +146,6 @@ public void afterAnalysis(AfterAnalysisAccess access) { .stream() .flatMap(ModuleLayerFeature::extractRequiredModuleNames) .collect(Collectors.toSet()); - allReachableModules.add("org.graalvm.nativeimage.librarysupport"); ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, allReachableModules); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); @@ -243,9 +242,9 @@ private List findApplicationModules(ModuleLayer runtimeBootLayer, List

    m.descriptor().name()) - .collect(Collectors.toList()); + .stream() + .map(m -> m.descriptor().name()) + .collect(Collectors.toList()); } catch (FindException | ResolutionException | SecurityException ex) { throw VMError.shouldNotReachHere("Failed to locate application modules.", ex); } @@ -253,7 +252,8 @@ private List findApplicationModules(ModuleLayer runtimeBootLayer, List

    module = runtimeBootLayer.findModule(moduleName); if (module.isEmpty()) { - throw VMError.shouldNotReachHere("Runtime boot module layer failed to include application module: " + moduleName); + // Module is not reachable + continue; } applicationModules.add(module.get()); } From 1e6db8a857c4f4a3ef14281391937315b1c0b72f Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Fri, 5 Nov 2021 17:10:53 +0100 Subject: [PATCH 06/16] Ignore unnamed modules during dynamic hub patching --- .../src/com/oracle/svm/hosted/ModuleLayerFeature.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 28b0bbce9369..07e74652b3e5 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -163,6 +163,9 @@ private void patchDynamicHubs(List types, SVMHost host, ModuleLaye continue; } Class clazz = type.getJavaClass(); + if (!clazz.getModule().isNamed()) { + continue; + } if (clazz.getModule().getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) { continue; } @@ -203,7 +206,7 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag .stream() .collect(Collectors.toMap(Module::getName, m -> new HostedRuntimeModulePair(m, runtimeBootLayer))); - Module builderModule = moduleLookupMap.get("org.graalvm.nativeimage.builder").hostedModule; + Module builderModule = ModuleLayerFeature.class.getModule(); assert builderModule != null; try { From b0cbe09ea5709acfa16e933bb69899cdfd02582f Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Mon, 8 Nov 2021 14:42:54 +0100 Subject: [PATCH 07/16] Mark methods as static where appropriate --- .../src/com/oracle/svm/hosted/ModuleLayerFeature.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 07e74652b3e5..65e7e45072d8 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -157,7 +157,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { /* * Updates module fields of all DynamicHubs with appropriate synthesized module instances */ - private void patchDynamicHubs(List types, SVMHost host, ModuleLayer runtimeBootLayer) { + private static void patchDynamicHubs(List types, SVMHost host, ModuleLayer runtimeBootLayer) { for (AnalysisType type : types) { if (!type.isReachable() || type.isArray()) { continue; @@ -239,7 +239,7 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag } } - private List findApplicationModules(ModuleLayer runtimeBootLayer, List applicationModulePath) { + private static List findApplicationModules(ModuleLayer runtimeBootLayer, List applicationModulePath) { List applicationModules = new ArrayList<>(); List applicationModuleNames; try { From f1fc11ad56494d578e782cb2db71bfaf8cf3dda9 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Tue, 16 Nov 2021 01:15:27 +0100 Subject: [PATCH 08/16] Transfer visibility for application modules --- .../oracle/svm/hosted/ModuleLayerFeature.java | 38 +++++++++++-------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 65e7e45072d8..d4ec0e3cef47 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -209,27 +209,33 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag Module builderModule = ModuleLayerFeature.class.getModule(); assert builderModule != null; + List toModify = new ArrayList<>(applicationModules.size() + 1); + toModify.add(builderModule); + toModify.addAll(applicationModules); + try { - for (Map.Entry e : moduleLookupMap.entrySet()) { - Module hostedModule = e.getValue().hostedModule; - if (hostedModule == builderModule) { - continue; - } - Module runtimeModule = e.getValue().runtimeModule; - if (builderModule.canRead(hostedModule)) { - for (Module appModule : applicationModules) { - moduleLayerFeatureUtils.addReads(appModule, runtimeModule); + for (Module m : toModify) { + for (Map.Entry e : moduleLookupMap.entrySet()) { + Module hostedModule = e.getValue().hostedModule; + if (hostedModule == m) { + continue; } - } - for (String pn : hostedModule.getPackages()) { - if (hostedModule.isOpen(pn, builderModule)) { + Module runtimeModule = e.getValue().runtimeModule; + if (m.canRead(hostedModule)) { for (Module appModule : applicationModules) { - moduleLayerFeatureUtils.addOpens(runtimeModule, pn, appModule); + moduleLayerFeatureUtils.addReads(appModule, runtimeModule); } } - if (hostedModule.isExported(pn, builderModule)) { - for (Module appModule : applicationModules) { - moduleLayerFeatureUtils.addExports(runtimeModule, pn, appModule); + for (String pn : hostedModule.getPackages()) { + if (hostedModule.isOpen(pn, m)) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addOpens(runtimeModule, pn, appModule); + } + } + if (hostedModule.isExported(pn, m)) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addExports(runtimeModule, pn, appModule); + } } } } From 50768cceb58cff50bdd8df6bb5913fbe898e8273 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Tue, 16 Nov 2021 01:21:17 +0100 Subject: [PATCH 09/16] Restore -ea flag for hellomodule --- substratevm/mx.substratevm/mx_substratevm.py | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/mx.substratevm/mx_substratevm.py b/substratevm/mx.substratevm/mx_substratevm.py index a2dcfc2546c9..f7e473a9c7df 100644 --- a/substratevm/mx.substratevm/mx_substratevm.py +++ b/substratevm/mx.substratevm/mx_substratevm.py @@ -1097,6 +1097,7 @@ def hellomodule(args): with native_image_context(hosted_assertions=False, config=config) as native_image: module_path_sep = ';' if mx.is_windows() else ':' moduletest_run_args = [ + '-ea', '--add-exports=moduletests.hello.lib/hello.privateLib=moduletests.hello.app', '--add-opens=moduletests.hello.lib/hello.privateLib2=moduletests.hello.app', '-p', module_path_sep.join(module_path), '-m', 'moduletests.hello.app' From ad1d42f0a11e5717e9c1a972a68882894708d08a Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Tue, 16 Nov 2021 15:16:11 +0100 Subject: [PATCH 10/16] Add assertion check to hellomodule --- .../oracle/svm/hosted/ModuleLayerFeature.java | 63 ++++++++++++------- .../hello.app/src/main/java/hello/Main.java | 13 +++- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index d4ec0e3cef47..e32b81cb3d79 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -67,13 +67,14 @@ * This feature: *

      *
    • synthesizes the runtime boot module layer
    • - *
    • ensures that fields/methods from the {@link ClassLoader} class are reachable in order to make - * native methods of the {@link Module} class work
    • + *
    • replicates build-time module relations at runtime
    • + *
    • patches dynamic hubs of every class with new module instances
    • *
    *

    * This feature synthesizes the runtime boot module layer by using type reachability information. If * a type is reachable, its module is also reachable and therefore should be included in the runtime - * boot module layer. + * boot module layer. If those modules require any additional modules, they will also be marked as + * reachable. *

    *

    * The configuration for the runtime boot module layer is resolved using the module reachability @@ -84,7 +85,7 @@ * {@link ModuleLayer#defineModulesWithOneLoader(Configuration, ClassLoader)}, because as a side * effect this will create a new class loader. Instead, we use a private constructor to construct * the {@link ModuleLayer} instance, which we then patch using the module reachability data provided - * to us by the analysis. + * to us by the analysis. This should be updated if JDK-8277013 gets resolved. *

    *

    * Because the result of this feature is dependant on the analysis results, and because this feature @@ -209,32 +210,39 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag Module builderModule = ModuleLayerFeature.class.getModule(); assert builderModule != null; - List toModify = new ArrayList<>(applicationModules.size() + 1); - toModify.add(builderModule); - toModify.addAll(applicationModules); - try { - for (Module m : toModify) { - for (Map.Entry e : moduleLookupMap.entrySet()) { - Module hostedModule = e.getValue().hostedModule; - if (hostedModule == m) { + for (Map.Entry e1 : moduleLookupMap.entrySet()) { + Module hostedFrom = e1.getValue().hostedModule; + Module runtimeFrom = e1.getValue().runtimeModule; + for (Map.Entry e2 : moduleLookupMap.entrySet()) { + Module hostedTo = e2.getValue().hostedModule; + if (hostedTo == hostedFrom) { continue; } - Module runtimeModule = e.getValue().runtimeModule; - if (m.canRead(hostedModule)) { - for (Module appModule : applicationModules) { - moduleLayerFeatureUtils.addReads(appModule, runtimeModule); + Module runtimeTo = e2.getValue().runtimeModule; + if (hostedFrom.canRead(hostedTo)) { + moduleLayerFeatureUtils.addReads(runtimeFrom, runtimeTo); + if (hostedFrom == builderModule) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addReads(appModule, runtimeTo); + } } } - for (String pn : hostedModule.getPackages()) { - if (hostedModule.isOpen(pn, m)) { - for (Module appModule : applicationModules) { - moduleLayerFeatureUtils.addOpens(runtimeModule, pn, appModule); + for (String pn : runtimeFrom.getPackages()) { + if (hostedFrom.isOpen(pn, hostedTo)) { + moduleLayerFeatureUtils.addOpens(runtimeFrom, pn, runtimeTo); + if (hostedTo == builderModule) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addOpens(runtimeFrom, pn, appModule); + } } } - if (hostedModule.isExported(pn, m)) { - for (Module appModule : applicationModules) { - moduleLayerFeatureUtils.addExports(runtimeModule, pn, appModule); + if (hostedFrom.isExported(pn, hostedTo)) { + moduleLayerFeatureUtils.addExports(runtimeFrom, pn, runtimeTo); + if (hostedTo == builderModule) { + for (Module appModule : applicationModules) { + moduleLayerFeatureUtils.addExports(runtimeFrom, pn, appModule); + } } } } @@ -295,6 +303,7 @@ private void patchRuntimeBootLayer(ModuleLayer runtimeBootLayer, Map everyoneSet; private final Constructor moduleConstructor; private final Field moduleLayerField; + private final Field moduleLoaderField; private final Field moduleReadsField; private final Field moduleOpenPackagesField; private final Field moduleExportedPackagesField; @@ -361,10 +371,12 @@ private static final class ModuleLayerFeatureUtils { allUnnamedModule = (Module) allUnnamedModuleField.get(null); moduleLayerField = findFieldByName(moduleClassFields, "layer"); + moduleLoaderField = findFieldByName(moduleClassFields, "loader"); moduleReadsField = findFieldByName(moduleClassFields, "reads"); moduleOpenPackagesField = findFieldByName(moduleClassFields, "openPackages"); moduleExportedPackagesField = findFieldByName(moduleClassFields, "exportedPackages"); moduleLayerField.setAccessible(true); + moduleLoaderField.setAccessible(true); moduleReadsField.setAccessible(true); moduleOpenPackagesField.setAccessible(true); moduleExportedPackagesField.setAccessible(true); @@ -566,5 +578,10 @@ void addOpens(Module module, String pn, Module other) throws IllegalAccessExcept prev.add(other == null ? allUnnamedModule : other); } } + + void clearJavaBaseLoaderField(ModuleLayer runtimeBootLayer) throws IllegalAccessException { + Module base = runtimeBootLayer.findModule("java.base").get(); + moduleLoaderField.set(base, null); + } } } diff --git a/substratevm/src/native-image-module-tests/hello.app/src/main/java/hello/Main.java b/substratevm/src/native-image-module-tests/hello.app/src/main/java/hello/Main.java index a642af8e8291..387386b55820 100644 --- a/substratevm/src/native-image-module-tests/hello.app/src/main/java/hello/Main.java +++ b/substratevm/src/native-image-module-tests/hello.app/src/main/java/hello/Main.java @@ -34,6 +34,8 @@ public class Main { public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + failIfAssertionsAreDisabled(); + Module helloAppModule = Main.class.getModule(); Module helloLibModule = Greeter.class.getModule(); testModuleObjects(helloAppModule, helloLibModule); @@ -49,10 +51,17 @@ public static void main(String[] args) throws NoSuchMethodException, InvocationT greetMethod.setAccessible(true); greetMethod.invoke(null); - System.out.println("Now testing boot module layer"); testBootLayer(helloAppModule, helloLibModule); } + private static void failIfAssertionsAreDisabled() { + boolean enabled = false; + assert enabled = true; + if (!enabled) { + throw new AssertionError("This example requires that assertions are enabled (-ea)"); + } + } + private static void testModuleObjects(Module helloAppModule, Module helloLibModule) { assert helloAppModule.getName().equals("moduletests.hello.app"); assert helloAppModule.isExported(Main.class.getPackageName()); @@ -73,6 +82,8 @@ private static void testModuleObjects(Module helloAppModule, Module helloLibModu @SuppressWarnings("OptionalGetWithoutIsPresent") private static void testBootLayer(Module helloAppModule, Module helloLibModule) { + System.out.println("Now testing boot module layer"); + ModuleLayer bootLayer = ModuleLayer.boot(); System.out.println("Now testing boot module layer configuration"); From 5887dacbda87dc61d0c3e40154ccb60e27705ee5 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 18 Nov 2021 10:43:03 +0100 Subject: [PATCH 11/16] Include synthetic modules from the hosted boot module layer --- .../oracle/svm/hosted/ModuleLayerFeature.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index e32b81cb3d79..bedb2e706bd9 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -123,7 +123,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { .stream() .map(Module::getName) .collect(Collectors.toSet()); - ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, baseModules); + ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, baseModules, Set.of()); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); } @@ -140,7 +140,11 @@ public void afterAnalysis(AfterAnalysisAccess access) { Set analysisReachableNamedModules = analysisReachableModules .filter(Module::isNamed) - .filter(m -> !m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) + .collect(Collectors.toSet()); + + Set analysisReachableSyntheticModules = analysisReachableNamedModules + .stream() + .filter(m -> m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) .collect(Collectors.toSet()); Set allReachableModules = analysisReachableNamedModules @@ -148,7 +152,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { .flatMap(ModuleLayerFeature::extractRequiredModuleNames) .collect(Collectors.toSet()); - ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, allReachableModules); + ModuleLayer runtimeBootLayer = synthesizeRuntimeBootLayer(accessImpl.imageClassLoader, allReachableModules, analysisReachableSyntheticModules); BootModuleLayerSupport.instance().setBootLayer(runtimeBootLayer); replicateVisibilityModifications(runtimeBootLayer, accessImpl.imageClassLoader, analysisReachableNamedModules); @@ -167,9 +171,6 @@ private static void patchDynamicHubs(List types, SVMHost host, Mod if (!clazz.getModule().isNamed()) { continue; } - if (clazz.getModule().getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) { - continue; - } DynamicHub hub = host.dynamicHub(type); String moduleName = clazz.getModule().getName(); Optional module = runtimeBootLayer.findModule(moduleName); @@ -188,11 +189,15 @@ private static Stream extractRequiredModuleNames(Module m) { return Stream.concat(Stream.of(m.getName()), requiredModules); } - private ModuleLayer synthesizeRuntimeBootLayer(ImageClassLoader cl, Set reachableModules) { + private ModuleLayer synthesizeRuntimeBootLayer(ImageClassLoader cl, Set reachableModules, Set syntheticModules) { Configuration cf = synthesizeRuntimeBootLayerConfiguration(cl.modulepath(), reachableModules); try { ModuleLayer runtimeBootLayer = moduleLayerConstructor.newInstance(cf, List.of(), null); Map nameToModule = moduleLayerFeatureUtils.synthesizeNameToModule(runtimeBootLayer, cl.getClassLoader()); + for (Module syntheticModule : syntheticModules) { + nameToModule.putIfAbsent(syntheticModule.getName(), syntheticModule); + moduleLayerFeatureUtils.patchModuleLayerField(syntheticModule, runtimeBootLayer); + } patchRuntimeBootLayer(runtimeBootLayer, nameToModule); return runtimeBootLayer; } catch (InstantiationException | IllegalAccessException | InvocationTargetException ex) { @@ -418,7 +423,7 @@ Map synthesizeNameToModule(ModuleLayer runtimeBootLayer, ClassLo ModuleDescriptor descriptor = mref.descriptor(); String name = descriptor.name(); Module m = moduleConstructor.newInstance(cl, descriptor); - moduleLayerField.set(m, runtimeBootLayer); + patchModuleLayerField(m, runtimeBootLayer); nameToModule.put(name, m); } @@ -583,5 +588,9 @@ void clearJavaBaseLoaderField(ModuleLayer runtimeBootLayer) throws IllegalAccess Module base = runtimeBootLayer.findModule("java.base").get(); moduleLoaderField.set(base, null); } + + void patchModuleLayerField(Module module, ModuleLayer runtimeBootLayer) throws IllegalAccessException { + moduleLayerField.set(module, runtimeBootLayer); + } } } From 52963d300bf7d209489d79adaa868c4a978ffdcd Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 18 Nov 2021 16:42:17 +0100 Subject: [PATCH 12/16] Ensure that jdk.jfr.events package is opened to the builder --- .../com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrFeature.java | 1 + 1 file changed, 1 insertion(+) diff --git a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrFeature.java b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrFeature.java index 7cae26757538..a3a49d7852f9 100644 --- a/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrFeature.java +++ b/substratevm/src/com.oracle.svm.jfr/src/com/oracle/svm/jfr/JfrFeature.java @@ -118,6 +118,7 @@ public List> getRequiredFeatures() { public void afterRegistration(AfterRegistrationAccess access) { ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.jfr", false); ModuleSupport.exportAndOpenAllPackagesToUnnamed("java.base", false); + ModuleSupport.exportAndOpenPackageToClass("jdk.jfr", "jdk.jfr.events", false, JfrFeature.class); ModuleSupport.exportAndOpenPackageToClass("jdk.internal.vm.ci", "jdk.vm.ci.hotspot", false, JfrEventSubstitution.class); // Initialize some parts of JFR/JFC at image build time. From c9266a8926496f05484c95727641f547ca40b1b4 Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Sat, 20 Nov 2021 12:45:05 +0100 Subject: [PATCH 13/16] Replicate ALL-UNNAMED and EVERYONE module relations --- .../oracle/svm/hosted/ModuleLayerFeature.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index bedb2e706bd9..e4c621e458c9 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -211,6 +211,8 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag Map moduleLookupMap = analysisReachableModules .stream() .collect(Collectors.toMap(Module::getName, m -> new HostedRuntimeModulePair(m, runtimeBootLayer))); + moduleLookupMap.putIfAbsent("ALL-UNNAMED", HostedRuntimeModulePair.withReplicatedHostedModule(moduleLayerFeatureUtils.allUnnamedModule)); + moduleLookupMap.putIfAbsent("EVERYONE", HostedRuntimeModulePair.withReplicatedHostedModule(moduleLayerFeatureUtils.everyoneModule)); Module builderModule = ModuleLayerFeature.class.getModule(); assert builderModule != null; @@ -218,6 +220,9 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag try { for (Map.Entry e1 : moduleLookupMap.entrySet()) { Module hostedFrom = e1.getValue().hostedModule; + if (!hostedFrom.isNamed()) { + continue; + } Module runtimeFrom = e1.getValue().runtimeModule; for (Map.Entry e2 : moduleLookupMap.entrySet()) { Module hostedTo = e2.getValue().hostedModule; @@ -339,12 +344,25 @@ public Set findAll() { } private static final class HostedRuntimeModulePair { + static HostedRuntimeModulePair withReplicatedHostedModule(Module module) { + return new HostedRuntimeModulePair(module, module); + } + final Module hostedModule; final Module runtimeModule; HostedRuntimeModulePair(Module hostedModule, ModuleLayer runtimeBootLayer) { this.hostedModule = hostedModule; - this.runtimeModule = runtimeBootLayer.findModule(hostedModule.getName()).orElseThrow(VMError::shouldNotReachHere); + this.runtimeModule = runtimeBootLayer.findModule(hostedModule.getName()).orElseThrow(() -> errorSupplier(hostedModule)); + } + + private HostedRuntimeModulePair(Module hosted, Module runtime) { + hostedModule = hosted; + runtimeModule = runtime; + } + + static RuntimeException errorSupplier(Module m) { + return VMError.shouldNotReachHere("Failed to find module " + m.getName() + " in the runtime boot module layer"); } } From 24fdee5a1817107bd86b5e86c12dde1b5415d14c Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Tue, 23 Nov 2021 11:29:03 +0100 Subject: [PATCH 14/16] Treat synthetic modules separately --- .../oracle/svm/hosted/ModuleLayerFeature.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index e4c621e458c9..1fd04fc3098b 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -144,7 +144,7 @@ public void afterAnalysis(AfterAnalysisAccess access) { Set analysisReachableSyntheticModules = analysisReachableNamedModules .stream() - .filter(m -> m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC)) + .filter(ModuleLayerFeatureUtils::isModuleSynthetic) .collect(Collectors.toSet()); Set allReachableModules = analysisReachableNamedModules @@ -230,7 +230,7 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag continue; } Module runtimeTo = e2.getValue().runtimeModule; - if (hostedFrom.canRead(hostedTo)) { + if (ModuleLayerFeatureUtils.isModuleSynthetic(hostedFrom) || hostedFrom.canRead(hostedTo)) { moduleLayerFeatureUtils.addReads(runtimeFrom, runtimeTo); if (hostedFrom == builderModule) { for (Module appModule : applicationModules) { @@ -239,7 +239,7 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag } } for (String pn : runtimeFrom.getPackages()) { - if (hostedFrom.isOpen(pn, hostedTo)) { + if (ModuleLayerFeatureUtils.isModuleSynthetic(hostedFrom) || hostedFrom.isOpen(pn, hostedTo)) { moduleLayerFeatureUtils.addOpens(runtimeFrom, pn, runtimeTo); if (hostedTo == builderModule) { for (Module appModule : applicationModules) { @@ -247,7 +247,7 @@ private void replicateVisibilityModifications(ModuleLayer runtimeBootLayer, Imag } } } - if (hostedFrom.isExported(pn, hostedTo)) { + if (ModuleLayerFeatureUtils.isModuleSynthetic(hostedFrom) || hostedFrom.isExported(pn, hostedTo)) { moduleLayerFeatureUtils.addExports(runtimeFrom, pn, runtimeTo); if (hostedTo == builderModule) { for (Module appModule : applicationModules) { @@ -418,6 +418,10 @@ private static Field findFieldByName(Field[] fields, String name) { return Arrays.stream(fields).filter(f -> f.getName().equals(name)).findAny().orElseThrow(VMError::shouldNotReachHere); } + static boolean isModuleSynthetic(Module m) { + return m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC); + } + /** * This method creates Module instances that will populate the runtime boot module layer of * the image. This implementation is copy-pasted from Module#defineModules(Configuration, @@ -462,6 +466,10 @@ Map synthesizeNameToModule(ModuleLayer runtimeBootLayer, ClassLo Module m2 = nameToModule.get(other.name()); reads.add(m2); } + + if (descriptor.isAutomatic()) { + reads.add(allUnnamedModule); + } moduleReadsField.set(m, reads); if (!descriptor.isOpen() && !descriptor.isAutomatic()) { From 21ee6c3a0adf2f4ea1a73fcbe0f6bdc47937214c Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 25 Nov 2021 15:30:45 +0100 Subject: [PATCH 15/16] Patch loader fields of boot layer modules --- .../oracle/svm/hosted/ModuleLayerFeature.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 1fd04fc3098b..4c6f69eb03d1 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -314,6 +314,12 @@ private void patchRuntimeBootLayer(ModuleLayer runtimeBootLayer, Map hostedModule = ModuleLayer.boot().findModule(m.getName()); + if (hostedModule.isPresent()) { + moduleLayerFeatureUtils.patchModuleLoaderField(m, hostedModule.get().getClassLoader()); + } + } } catch (IllegalAccessException ex) { throw VMError.shouldNotReachHere("Failed to patch the runtime boot module layer.", ex); } @@ -610,13 +616,17 @@ void addOpens(Module module, String pn, Module other) throws IllegalAccessExcept } } - void clearJavaBaseLoaderField(ModuleLayer runtimeBootLayer) throws IllegalAccessException { - Module base = runtimeBootLayer.findModule("java.base").get(); - moduleLoaderField.set(base, null); - } - void patchModuleLayerField(Module module, ModuleLayer runtimeBootLayer) throws IllegalAccessException { moduleLayerField.set(module, runtimeBootLayer); } + + void patchModuleLoaderField(Module module, ClassLoader loader) throws IllegalAccessException { + moduleLoaderField.set(module, loader); + } + + void clearJavaBaseLoaderField(ModuleLayer runtimeBootLayer) throws IllegalAccessException { + Module base = runtimeBootLayer.findModule("java.base").get(); + patchModuleLoaderField(base, null); + } } } From bd3ce8e2af1d6b44a9769bd07e684967c0e5a6cc Mon Sep 17 00:00:00 2001 From: ivan-ristovic Date: Thu, 25 Nov 2021 16:48:07 +0100 Subject: [PATCH 16/16] Patch Module.loader fields of synthesized modules --- .../com/oracle/svm/hosted/ModuleLayerFeature.java | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java index 4c6f69eb03d1..3c5130849d29 100644 --- a/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java +++ b/substratevm/src/com.oracle.svm.hosted.jdk11/src/com/oracle/svm/hosted/ModuleLayerFeature.java @@ -313,11 +313,10 @@ private void patchRuntimeBootLayer(ModuleLayer runtimeBootLayer, Map hostedModule = ModuleLayer.boot().findModule(m.getName()); - if (hostedModule.isPresent()) { - moduleLayerFeatureUtils.patchModuleLoaderField(m, hostedModule.get().getClassLoader()); + if (hostedModule.isPresent() && hostedModule.get().getClassLoader() == null) { + moduleLayerFeatureUtils.patchModuleLoaderField(m); } } } catch (IllegalAccessException ex) { @@ -620,13 +619,8 @@ void patchModuleLayerField(Module module, ModuleLayer runtimeBootLayer) throws I moduleLayerField.set(module, runtimeBootLayer); } - void patchModuleLoaderField(Module module, ClassLoader loader) throws IllegalAccessException { - moduleLoaderField.set(module, loader); - } - - void clearJavaBaseLoaderField(ModuleLayer runtimeBootLayer) throws IllegalAccessException { - Module base = runtimeBootLayer.findModule("java.base").get(); - patchModuleLoaderField(base, null); + void patchModuleLoaderField(Module module) throws IllegalAccessException { + moduleLoaderField.set(module, null); } } }