Skip to content

Commit 1c7dde9

Browse files
committed
Reuse ModuleBootstrap.boot2()
1 parent 99e8537 commit 1c7dde9

File tree

4 files changed

+193
-12
lines changed

4 files changed

+193
-12
lines changed

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/DefaultOptionHandler.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ class DefaultOptionHandler extends NativeImage.OptionHandler<NativeImage> {
4343
private static final String newStyleClasspathOptionName = "--class-path";
4444

4545
static final String addModulesOption = "--add-modules";
46-
private static final String addModulesErrorMessage = " requires modules to be specified";
46+
static final String limitModulesOption = "--limit-modules";
47+
private static final String moduleSetModifierOptionErrorMessage = " requires modules to be specified";
4748

4849
/* Defunct legacy options that we have to accept to maintain backward compatibility */
4950
private static final String noServerOption = "--no-server";
@@ -95,11 +96,20 @@ public boolean consume(ArgumentQueue args) {
9596
args.poll();
9697
String addModulesArgs = args.poll();
9798
if (addModulesArgs == null) {
98-
NativeImage.showError(headArg + addModulesErrorMessage);
99+
NativeImage.showError(headArg + moduleSetModifierOptionErrorMessage);
99100
}
100101
nativeImage.addImageBuilderJavaArgs(addModulesOption, addModulesArgs);
101102
nativeImage.addAddedModules(addModulesArgs);
102103
return true;
104+
case limitModulesOption:
105+
args.poll();
106+
String limitModulesArgs = args.poll();
107+
if (limitModulesArgs == null) {
108+
NativeImage.showError(headArg + moduleSetModifierOptionErrorMessage);
109+
}
110+
nativeImage.addImageBuilderJavaArgs(limitModulesOption, limitModulesArgs);
111+
nativeImage.addLimitedModules(limitModulesArgs);
112+
return true;
103113
case "-jar":
104114
args.poll();
105115
String jarFilePathStr = args.poll();
@@ -179,12 +189,22 @@ public boolean consume(ArgumentQueue args) {
179189
args.poll();
180190
String addModulesArgs = headArg.substring(addModulesOption.length() + 1);
181191
if (addModulesArgs.isEmpty()) {
182-
NativeImage.showError(headArg + addModulesErrorMessage);
192+
NativeImage.showError(headArg + moduleSetModifierOptionErrorMessage);
183193
}
184194
nativeImage.addImageBuilderJavaArgs(addModulesOption, addModulesArgs);
185195
nativeImage.addAddedModules(addModulesArgs);
186196
return true;
187197
}
198+
if (headArg.startsWith(limitModulesOption + "=")) {
199+
args.poll();
200+
String limitModulesArgs = headArg.substring(limitModulesOption.length() + 1);
201+
if (limitModulesArgs.isEmpty()) {
202+
NativeImage.showError(headArg + moduleSetModifierOptionErrorMessage);
203+
}
204+
nativeImage.addImageBuilderJavaArgs(limitModulesOption, limitModulesArgs);
205+
nativeImage.addLimitedModules(limitModulesArgs);
206+
return true;
207+
}
188208
if (headArg.startsWith("@") && !disableAtFiles) {
189209
args.poll();
190210
headArg = headArg.substring(1);

substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ private static <T> String oR(OptionKey<T> option) {
292292

293293
private final List<ExcludeConfig> excludedConfigs = new ArrayList<>();
294294
private final LinkedHashSet<String> addModules = new LinkedHashSet<>();
295+
private final LinkedHashSet<String> limitModules = new LinkedHashSet<>();
295296

296297
private long imageBuilderPid = -1;
297298

@@ -1186,6 +1187,9 @@ private int completeImageBuild() {
11861187
if (!addModules.isEmpty()) {
11871188
imageBuilderJavaArgs.add("-D" + ModuleSupport.PROPERTY_IMAGE_EXPLICITLY_ADDED_MODULES + "=" + String.join(",", addModules));
11881189
}
1190+
if (!limitModules.isEmpty()) {
1191+
imageBuilderJavaArgs.add("-D" + ModuleSupport.PROPERTY_IMAGE_EXPLICITLY_LIMITED_MODULES + "=" + String.join(",", limitModules));
1192+
}
11891193
if (config.modulePathBuild && !finalImageClasspath.isEmpty()) {
11901194
imageBuilderJavaArgs.add(DefaultOptionHandler.addModulesOption + "=ALL-DEFAULT");
11911195
}
@@ -1617,6 +1621,10 @@ public void addAddedModules(String addModulesArg) {
16171621
addModules.addAll(Arrays.asList(SubstrateUtil.split(addModulesArg, ",")));
16181622
}
16191623

1624+
public void addLimitedModules(String limitModulesArg) {
1625+
limitModules.addAll(Arrays.asList(SubstrateUtil.split(limitModulesArg, ",")));
1626+
}
1627+
16201628
void addImageBuilderClasspath(Path classpath) {
16211629
imageBuilderClasspath.add(canonicalize(classpath));
16221630
}

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

Lines changed: 155 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,19 @@
5353
import java.util.stream.Collectors;
5454
import java.util.stream.Stream;
5555

56+
import jdk.internal.module.SystemModuleFinders;
57+
import org.graalvm.compiler.options.OptionValues;
5658
import org.graalvm.nativeimage.ImageSingletons;
5759

5860
import com.oracle.graal.pointsto.meta.AnalysisType;
5961
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
62+
import com.oracle.svm.core.SubstrateOptions;
6063
import com.oracle.svm.core.SubstrateUtil;
6164
import com.oracle.svm.core.feature.InternalFeature;
6265
import com.oracle.svm.core.jdk.BootModuleLayerSupport;
6366
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
6467
import com.oracle.svm.core.util.VMError;
68+
import com.oracle.svm.core.util.UserError;
6569
import com.oracle.svm.util.ModuleSupport;
6670
import com.oracle.svm.util.ReflectionUtil;
6771

@@ -152,15 +156,10 @@ public void afterAnalysis(AfterAnalysisAccess access) {
152156
* Parse explicitly added modules via --add-modules. This is done early as this information
153157
* is required when filtering the analysis reachable module set.
154158
*/
155-
Set<String> extraModules = new HashSet<>();
156-
String explicitlyAddedModules = System.getProperty(ModuleSupport.PROPERTY_IMAGE_EXPLICITLY_ADDED_MODULES, "");
157-
if (!explicitlyAddedModules.isEmpty()) {
158-
extraModules.addAll(Arrays.asList(SubstrateUtil.split(explicitlyAddedModules, ",")));
159-
}
160-
161-
List<String> nonExplicit = List.of("ALL-DEFAULT", "ALL-SYSTEM", "ALL-MODULE-PATH");
159+
Set<String> extraModules = ModuleLayerFeatureUtils.parseModuleSetModifierProperty(ModuleSupport.PROPERTY_IMAGE_EXPLICITLY_ADDED_MODULES);
162160

163-
Set<Module> runtimeImageModules = calculateRootModulesAndUpdateExtraModules(accessImpl, nonExplicit, extraModules);
161+
Set<Module> runtimeImageModules = calculateRootModulesAndUpdateExtraModules(accessImpl, ModuleSupport.nonExplicitModules, extraModules);
162+
// Set<Module> runtimeImageModules = calculateRootModules(accessImpl, extraModules);
164163

165164
Set<Module> runtimeImageNamedModules = runtimeImageModules
166165
.stream()
@@ -172,7 +171,7 @@ public void afterAnalysis(AfterAnalysisAccess access) {
172171
* process.
173172
*/
174173
extraModules.addAll(ImageSingletons.lookup(ResourcesFeature.class).includedResourcesModules);
175-
extraModules.stream().filter(Predicate.not(nonExplicit::contains)).forEach(moduleName -> {
174+
extraModules.stream().filter(Predicate.not(ModuleSupport.nonExplicitModules::contains)).forEach(moduleName -> {
176175
Optional<?> module = accessImpl.imageClassLoader.findModule(moduleName);
177176
if (module.isEmpty()) {
178177
VMError.shouldNotReachHere("Explicitly required module " + moduleName + " is not available");
@@ -270,6 +269,108 @@ private static Set<Module> calculateRootModulesAndUpdateExtraModules(FeatureImpl
270269
return rootModules.collect(Collectors.toSet());
271270
}
272271

272+
/**
273+
* See jdk.internal.module.ModuleBootstrap#boot2() method for more details.
274+
*/
275+
private Set<String> calculateRootModules(FeatureImpl.AfterAnalysisAccessImpl accessImpl, Collection<String> extraModules) {
276+
String mainModule = moduleLayerFeatureUtils.getMainModuleName();
277+
List<Path> appModulePath = accessImpl.imageClassLoader.applicationModulePath();
278+
boolean haveAppModulePath = !appModulePath.isEmpty();
279+
Set<String> limitModules = ModuleLayerFeatureUtils.parseModuleSetModifierProperty(ModuleSupport.PROPERTY_IMAGE_EXPLICITLY_LIMITED_MODULES);
280+
281+
Object systemModules = null;
282+
ModuleFinder systemModuleFinder;
283+
284+
if (!haveAppModulePath && extraModules.isEmpty() && limitModules.isEmpty()) {
285+
systemModules = moduleLayerFeatureUtils.invokeSystemModuleFinderSystemModules(mainModule);
286+
}
287+
if (systemModules == null) {
288+
// all system modules are observable
289+
systemModules = moduleLayerFeatureUtils.invokeSystemModuleFinderAllSystemModules();
290+
}
291+
if (systemModules != null) {
292+
// images build
293+
systemModuleFinder = moduleLayerFeatureUtils.invokeSystemModuleFinderOf(systemModules);
294+
} else {
295+
// exploded build or testing
296+
throw UserError.abort("Exploded builds are not supported.");
297+
}
298+
299+
ModuleFinder appModulePathFinder = ModuleFinder.of(accessImpl.imageClassLoader.applicationModulePath().toArray(new Path[0]));
300+
ModuleFinder finder = haveAppModulePath ? ModuleFinder.compose(systemModuleFinder, appModulePathFinder) : systemModuleFinder;
301+
302+
// The root modules to resolve
303+
Set<String> roots = new HashSet<>();
304+
305+
// Launcher -m option to specify the main/initial module
306+
if (mainModule != null)
307+
roots.add(mainModule);
308+
309+
// Additional module(s) specified by --add-modules
310+
boolean addAllDefaultModules = false;
311+
boolean addAllSystemModules = false;
312+
boolean addAllApplicationModules = false;
313+
for (String mod : extraModules) {
314+
switch (mod) {
315+
case ModuleSupport.MODULE_SET_ALL_DEFAULT:
316+
addAllDefaultModules = true;
317+
break;
318+
case ModuleSupport.MODULE_SET_ALL_SYSTEM:
319+
addAllSystemModules = true;
320+
break;
321+
case ModuleSupport.MODULE_SET_ALL_MODULE_PATH:
322+
addAllApplicationModules = true;
323+
break;
324+
default:
325+
roots.add(mod);
326+
}
327+
}
328+
329+
/*
330+
// --limit-modules
331+
if (!limitModules.isEmpty()) {
332+
finder = limitFinder(finder, limitModules, roots);
333+
}
334+
335+
// If there is no initial module specified then assume that the initial
336+
// module is the unnamed module of the application class loader. This
337+
// is implemented by resolving all observable modules that export an
338+
// API. Modules that have the DO_NOT_RESOLVE_BY_DEFAULT bit set in
339+
// their ModuleResolution attribute flags are excluded from the
340+
// default set of roots.
341+
if (mainModule == null || addAllDefaultModules) {
342+
roots.addAll(DefaultRoots.compute(systemModuleFinder, finder));
343+
}
344+
345+
// If `--add-modules ALL-SYSTEM` is specified then all observable system
346+
// modules will be resolved.
347+
if (addAllSystemModules) {
348+
ModuleFinder f = finder; // observable modules
349+
systemModuleFinder.findAll()
350+
.stream()
351+
.map(ModuleReference::descriptor)
352+
.map(ModuleDescriptor::name)
353+
.filter(mn -> f.find(mn).isPresent()) // observable
354+
.forEach(roots::add);
355+
}
356+
357+
// If `--add-modules ALL-MODULE-PATH` is specified then all observable
358+
// modules on the application module path will be resolved.
359+
if (appModulePath != null && addAllApplicationModules) {
360+
ModuleFinder f = finder; // observable modules
361+
appModulePath.findAll()
362+
.stream()
363+
.map(ModuleReference::descriptor)
364+
.map(ModuleDescriptor::name)
365+
.filter(mn -> f.find(mn).isPresent()) // observable
366+
.forEach(mn -> roots.add(mn));
367+
}
368+
369+
*/
370+
371+
return roots;
372+
}
373+
273374
private static boolean typeIsReachable(AnalysisType t) {
274375
return t.isReachable() && !t.isArray();
275376
}
@@ -527,6 +628,9 @@ private static final class ModuleLayerFeatureUtils {
527628
private final Field moduleOpenPackagesField;
528629
private final Field moduleExportedPackagesField;
529630
private final Method moduleFindModuleMethod;
631+
private final Method systemModuleFindersAllSystemModulesMethod;
632+
private final Method systemModuleFindersOfMethod;
633+
private final Method systemModuleFindersSystemModulesMethod;
530634
private final Constructor<ModuleLayer> moduleLayerConstructor;
531635
private final Field moduleLayerNameToModuleField;
532636
private final Field moduleLayerParentsField;
@@ -569,6 +673,10 @@ private static final class ModuleLayerFeatureUtils {
569673
moduleConstructor = ReflectionUtil.lookupConstructor(Module.class, ClassLoader.class, ModuleDescriptor.class);
570674
moduleFindModuleMethod = ReflectionUtil.lookupMethod(Module.class, "findModule", String.class, Map.class, Map.class, List.class);
571675

676+
systemModuleFindersAllSystemModulesMethod = ReflectionUtil.lookupMethod(SystemModuleFinders.class, "allSystemModules");
677+
systemModuleFindersOfMethod = ReflectionUtil.lookupMethod(SystemModuleFinders.class, "of", Class.forName("jdk.internal.module.SystemModules"));
678+
systemModuleFindersSystemModulesMethod = ReflectionUtil.lookupMethod(SystemModuleFinders.class, "systemModules", String.class);
679+
572680
moduleLayerConstructor = ReflectionUtil.lookupConstructor(ModuleLayer.class, Configuration.class, List.class, Function.class);
573681
moduleLayerNameToModuleField = ReflectionUtil.lookupField(ModuleLayer.class, "nameToModule");
574682
moduleLayerParentsField = ReflectionUtil.lookupField(ModuleLayer.class, "parents");
@@ -590,6 +698,15 @@ private static boolean isModuleSynthetic(Module m) {
590698
return m.getDescriptor().modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC);
591699
}
592700

701+
static Set<String> parseModuleSetModifierProperty(String prop) {
702+
Set<String> specifiedModules = new HashSet<>();
703+
String args = System.getProperty(prop, "");
704+
if (!args.isEmpty()) {
705+
specifiedModules.addAll(Arrays.asList(SubstrateUtil.split(args, ",")));
706+
}
707+
return specifiedModules;
708+
}
709+
593710
static int distanceFromBootModuleLayer(ModuleLayer layer) {
594711
if (layer == ModuleLayer.boot()) {
595712
return 0;
@@ -601,6 +718,11 @@ static int distanceFromBootModuleLayer(ModuleLayer layer) {
601718
.orElse(0);
602719
}
603720

721+
public String getMainModuleName() {
722+
OptionValues parsedHostedOptions = imageClassLoader.classLoaderSupport.getParsedHostedOptions();
723+
return SubstrateOptions.Module.getValue(parsedHostedOptions);
724+
}
725+
604726
public Module getRuntimeModuleForHostedModule(Module hostedModule, boolean optional) {
605727
if (hostedModule.isNamed()) {
606728
return getRuntimeModuleForHostedModule(hostedModule.getClassLoader(), hostedModule.getName(), optional);
@@ -894,5 +1016,29 @@ ClassLoader getClassLoaderForModuleInModuleLayer(ModuleLayer hostedModuleLayer,
8941016
Optional<Module> module = hostedModuleLayer.findModule(name);
8951017
return module.isPresent() ? module.get().getClassLoader() : imageClassLoader.getClassLoader();
8961018
}
1019+
1020+
Object invokeSystemModuleFinderAllSystemModules() {
1021+
try {
1022+
return systemModuleFindersAllSystemModulesMethod.invoke(null);
1023+
} catch (ReflectiveOperationException e) {
1024+
throw VMError.shouldNotReachHere("Failed to reflectively invoke SystemModuleFinders.allSystemModules().", e);
1025+
}
1026+
}
1027+
1028+
ModuleFinder invokeSystemModuleFinderOf(Object systemModules) {
1029+
try {
1030+
return (ModuleFinder) systemModuleFindersOfMethod.invoke(null, systemModules);
1031+
} catch (ReflectiveOperationException e) {
1032+
throw VMError.shouldNotReachHere("Failed to reflectively invoke SystemModuleFinders.of().", e);
1033+
}
1034+
}
1035+
1036+
Object invokeSystemModuleFinderSystemModules(String mainModule) {
1037+
try {
1038+
return systemModuleFindersSystemModulesMethod.invoke(null, mainModule);
1039+
} catch (ReflectiveOperationException e) {
1040+
throw VMError.shouldNotReachHere("Failed to reflectively invoke SystemModuleFinders.systemModules().", e);
1041+
}
1042+
}
8971043
}
8981044
}

substratevm/src/com.oracle.svm.util/src/com/oracle/svm/util/ModuleSupport.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.oracle.svm.util;
2626

27+
import java.util.List;
2728
import java.util.Objects;
2829
import java.util.Optional;
2930
import java.util.Set;
@@ -35,8 +36,14 @@
3536

3637
public final class ModuleSupport {
3738

39+
public static final String MODULE_SET_ALL_DEFAULT = "ALL-DEFAULT";
40+
public static final String MODULE_SET_ALL_SYSTEM = "ALL-SYSTEM";
41+
public static final String MODULE_SET_ALL_MODULE_PATH = "ALL-MODULE-PATH";
42+
public static final List<String> nonExplicitModules = List.of(MODULE_SET_ALL_DEFAULT, MODULE_SET_ALL_SYSTEM, MODULE_SET_ALL_MODULE_PATH);
43+
3844
public static final String ENV_VAR_USE_MODULE_SYSTEM = "USE_NATIVE_IMAGE_JAVA_PLATFORM_MODULE_SYSTEM";
3945
public static final String PROPERTY_IMAGE_EXPLICITLY_ADDED_MODULES = "org.graalvm.nativeimage.module.addmods";
46+
public static final String PROPERTY_IMAGE_EXPLICITLY_LIMITED_MODULES = "org.graalvm.nativeimage.module.limitmods";
4047
public static final boolean modulePathBuild = isModulePathBuild();
4148

4249
private ModuleSupport() {

0 commit comments

Comments
 (0)