5353import java .util .stream .Collectors ;
5454import java .util .stream .Stream ;
5555
56+ import jdk .internal .module .SystemModuleFinders ;
57+ import org .graalvm .compiler .options .OptionValues ;
5658import org .graalvm .nativeimage .ImageSingletons ;
5759
5860import com .oracle .graal .pointsto .meta .AnalysisType ;
5961import com .oracle .graal .pointsto .meta .AnalysisUniverse ;
62+ import com .oracle .svm .core .SubstrateOptions ;
6063import com .oracle .svm .core .SubstrateUtil ;
6164import com .oracle .svm .core .feature .InternalFeature ;
6265import com .oracle .svm .core .jdk .BootModuleLayerSupport ;
6366import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
6467import com .oracle .svm .core .util .VMError ;
68+ import com .oracle .svm .core .util .UserError ;
6569import com .oracle .svm .util .ModuleSupport ;
6670import 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}
0 commit comments