use of java.lang.module.ModuleFinder in project Bytecoder by mirkosertic.
the class ModuleBootstrap method limitFinder.
/**
* Returns a ModuleFinder that limits observability to the given root
* modules, their transitive dependences, plus a set of other modules.
*/
private static ModuleFinder limitFinder(ModuleFinder finder, Set<String> roots, Set<String> otherMods) {
// resolve all root modules
Configuration cf = Configuration.empty().resolve(finder, ModuleFinder.of(), roots);
// module name -> reference
Map<String, ModuleReference> map = new HashMap<>();
// root modules and their transitive dependences
cf.modules().stream().map(ResolvedModule::reference).forEach(mref -> map.put(mref.descriptor().name(), mref));
// additional modules
otherMods.stream().map(finder::find).flatMap(Optional::stream).forEach(mref -> map.putIfAbsent(mref.descriptor().name(), mref));
// set of modules that are observable
Set<ModuleReference> mrefs = new HashSet<>(map.values());
return new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
return Optional.ofNullable(map.get(name));
}
@Override
public Set<ModuleReference> findAll() {
return mrefs;
}
};
}
use of java.lang.module.ModuleFinder in project Bytecoder by mirkosertic.
the class Modules method loadModule.
/**
* Called by the VM to load a system module, typically "java.instrument" or
* "jdk.management.agent". If the module is not loaded then it is resolved
* and loaded (along with any dependences that weren't previously loaded)
* into a child layer.
*/
public static synchronized Module loadModule(String name) {
ModuleLayer top = topLayer;
if (top == null)
top = ModuleLayer.boot();
Module module = top.findModule(name).orElse(null);
if (module != null) {
// module already loaded
return module;
}
// resolve the module with the top-most layer as the parent
ModuleFinder empty = ModuleFinder.of();
ModuleFinder finder = ModuleBootstrap.unlimitedFinder();
Set<String> roots = Set.of(name);
Configuration cf = top.configuration().resolveAndBind(empty, finder, roots);
// create the child layer
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
ModuleLayer newLayer = top.defineModules(cf, clf);
// add qualified exports/opens to give access to modules in child layer
Map<String, Module> map = newLayer.modules().stream().collect(Collectors.toMap(Module::getName, Function.identity()));
ModuleLayer layer = top;
while (layer != null) {
for (Module m : layer.modules()) {
// qualified exports
m.getDescriptor().exports().stream().filter(ModuleDescriptor.Exports::isQualified).forEach(e -> e.targets().forEach(target -> {
Module other = map.get(target);
if (other != null) {
addExports(m, e.source(), other);
}
}));
// qualified opens
m.getDescriptor().opens().stream().filter(ModuleDescriptor.Opens::isQualified).forEach(o -> o.targets().forEach(target -> {
Module other = map.get(target);
if (other != null) {
addOpens(m, o.source(), other);
}
}));
}
List<ModuleLayer> parents = layer.parents();
assert parents.size() <= 1;
layer = parents.isEmpty() ? null : parents.get(0);
}
// update security manager before making types visible
JLA.addNonExportedPackages(newLayer);
// update the built-in class loaders to make the types visible
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
String mn = mref.descriptor().name();
ClassLoader cl = clf.apply(mn);
if (cl == null) {
BootLoader.loadModule(mref);
} else {
((BuiltinClassLoader) cl).loadModule(mref);
}
}
// new top layer
topLayer = newLayer;
// return module
return newLayer.findModule(name).orElseThrow(() -> new InternalError("module not loaded"));
}
use of java.lang.module.ModuleFinder in project Bytecoder by mirkosertic.
the class SystemModuleFinders method ofSystem.
/**
* Returns the ModuleFinder to find all system modules. Supports both
* images and exploded builds.
*
* @apiNote Used by ModuleFinder.ofSystem()
*/
public static ModuleFinder ofSystem() {
ModuleFinder finder = cachedSystemModuleFinder;
if (finder != null) {
return finder;
}
// probe to see if this is an images build
String home = System.getProperty("java.home");
Path modules = Paths.get(home, "lib", "modules");
if (Files.isRegularFile(modules)) {
if (USE_FAST_PATH) {
SystemModules systemModules = allSystemModules();
if (systemModules != null) {
finder = of(systemModules);
}
}
// fall back to parsing the module-info.class files in image
if (finder == null) {
finder = ofModuleInfos();
}
cachedSystemModuleFinder = finder;
return finder;
}
// exploded build (do not cache module finder)
Path dir = Paths.get(home, "modules");
if (!Files.isDirectory(dir))
throw new InternalError("Unable to detect the run-time image");
ModuleFinder f = ModulePath.of(ModuleBootstrap.patcher(), dir);
return new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
PrivilegedAction<Optional<ModuleReference>> pa = () -> f.find(name);
return AccessController.doPrivileged(pa);
}
@Override
public Set<ModuleReference> findAll() {
PrivilegedAction<Set<ModuleReference>> pa = f::findAll;
return AccessController.doPrivileged(pa);
}
};
}
use of java.lang.module.ModuleFinder in project Bytecoder by mirkosertic.
the class ModuleBootstrap method boot.
/**
* Initialize the module system, returning the boot layer.
*
* @see java.lang.System#initPhase2()
*/
public static ModuleLayer boot() throws Exception {
// Step 0: Command line options
long t0 = System.nanoTime();
ModuleFinder upgradeModulePath = finderFor("jdk.module.upgrade.path");
ModuleFinder appModulePath = finderFor("jdk.module.path");
boolean isPatched = patcher.hasPatches();
String mainModule = System.getProperty("jdk.module.main");
Set<String> addModules = addModules();
Set<String> limitModules = limitModules();
PrintStream traceOutput = null;
String trace = getAndRemoveProperty("jdk.module.showModuleResolution");
if (trace != null && Boolean.parseBoolean(trace))
traceOutput = System.out;
// Step 1: The observable system modules, either all system modules
// or the system modules pre-generated for the initial module (the
// initial module may be the unnamed module). If the system modules
// are pre-generated for the initial module then resolution can be
// skipped.
long t1 = System.nanoTime();
SystemModules systemModules = null;
ModuleFinder systemModuleFinder;
boolean haveModulePath = (appModulePath != null || upgradeModulePath != null);
boolean needResolution = true;
if (!haveModulePath && addModules.isEmpty() && limitModules.isEmpty()) {
systemModules = SystemModuleFinders.systemModules(mainModule);
if (systemModules != null && !isPatched && (traceOutput == null)) {
needResolution = false;
}
}
if (systemModules == null) {
// all system modules are observable
systemModules = SystemModuleFinders.allSystemModules();
}
if (systemModules != null) {
// images build
systemModuleFinder = SystemModuleFinders.of(systemModules);
} else {
// exploded build or testing
systemModules = new ExplodedSystemModules();
systemModuleFinder = SystemModuleFinders.ofSystem();
}
Counters.add("jdk.module.boot.1.systemModulesTime", t1);
// Step 2: Define and load java.base. This patches all classes loaded
// to date so that they are members of java.base. Once java.base is
// loaded then resources in java.base are available for error messages
// needed from here on.
long t2 = System.nanoTime();
ModuleReference base = systemModuleFinder.find(JAVA_BASE).orElse(null);
if (base == null)
throw new InternalError(JAVA_BASE + " not found");
URI baseUri = base.location().orElse(null);
if (baseUri == null)
throw new InternalError(JAVA_BASE + " does not have a location");
BootLoader.loadModule(base);
Modules.defineModule(null, base.descriptor(), baseUri);
Counters.add("jdk.module.boot.2.defineBaseTime", t2);
if (getAndRemoveProperty("jdk.module.validation") != null) {
return createBootLayerForValidation();
}
// Step 3: If resolution is needed then create the module finder and
// the set of root modules to resolve.
long t3 = System.nanoTime();
ModuleFinder savedModuleFinder = null;
ModuleFinder finder;
Set<String> roots;
if (needResolution) {
// upgraded modules override the modules in the run-time image
if (upgradeModulePath != null)
systemModuleFinder = ModuleFinder.compose(upgradeModulePath, systemModuleFinder);
// The module finder: [--upgrade-module-path] system [--module-path]
if (appModulePath != null) {
finder = ModuleFinder.compose(systemModuleFinder, appModulePath);
} else {
finder = systemModuleFinder;
}
// The root modules to resolve
roots = new HashSet<>();
// launcher -m option to specify the main/initial module
if (mainModule != null)
roots.add(mainModule);
// additional module(s) specified by --add-modules
boolean addAllDefaultModules = false;
boolean addAllSystemModules = false;
boolean addAllApplicationModules = false;
for (String mod : addModules) {
switch(mod) {
case ALL_DEFAULT:
addAllDefaultModules = true;
break;
case ALL_SYSTEM:
addAllSystemModules = true;
break;
case ALL_MODULE_PATH:
addAllApplicationModules = true;
break;
default:
roots.add(mod);
}
}
// --limit-modules
savedModuleFinder = finder;
if (!limitModules.isEmpty()) {
finder = limitFinder(finder, limitModules, roots);
}
// the default set of roots.
if (mainModule == null || addAllDefaultModules) {
roots.addAll(DefaultRoots.compute(systemModuleFinder, finder));
}
// modules will be resolved.
if (addAllSystemModules) {
// observable modules
ModuleFinder f = finder;
systemModuleFinder.findAll().stream().map(ModuleReference::descriptor).map(ModuleDescriptor::name).filter(// observable
mn -> f.find(mn).isPresent()).forEach(mn -> roots.add(mn));
}
// modules on the application module path will be resolved.
if (appModulePath != null && addAllApplicationModules) {
// observable modules
ModuleFinder f = finder;
appModulePath.findAll().stream().map(ModuleReference::descriptor).map(ModuleDescriptor::name).filter(// observable
mn -> f.find(mn).isPresent()).forEach(mn -> roots.add(mn));
}
} else {
// no resolution case
finder = systemModuleFinder;
roots = null;
}
Counters.add("jdk.module.boot.3.optionsAndRootsTime", t3);
// Step 4: Resolve the root modules, with service binding, to create
// the configuration for the boot layer. If resolution is not needed
// then create the configuration for the boot layer from the
// readability graph created at link time.
long t4 = System.nanoTime();
Configuration cf;
if (needResolution) {
cf = JLMA.resolveAndBind(finder, roots, traceOutput);
} else {
Map<String, Set<String>> map = systemModules.moduleReads();
cf = JLMA.newConfiguration(systemModuleFinder, map);
}
// check that modules specified to --patch-module are resolved
if (isPatched) {
patcher.patchedModules().stream().filter(mn -> !cf.findModule(mn).isPresent()).forEach(mn -> warnUnknownModule(PATCH_MODULE, mn));
}
Counters.add("jdk.module.boot.4.resolveTime", t4);
// Step 5: Map the modules in the configuration to class loaders.
// The static configuration provides the mapping of standard and JDK
// modules to the boot and platform loaders. All other modules (JDK
// tool modules, and both explicit and automatic modules on the
// application module path) are defined to the application class
// loader.
long t5 = System.nanoTime();
// mapping of modules to class loaders
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
// loaded from the runtime image
if (haveModulePath) {
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
String name = mref.descriptor().name();
ClassLoader cl = clf.apply(name);
if (cl == null) {
if (upgradeModulePath != null && upgradeModulePath.find(name).isPresent())
fail(name + ": cannot be loaded from upgrade module path");
if (!systemModuleFinder.find(name).isPresent())
fail(name + ": cannot be loaded from application module path");
}
}
}
// check for split packages in the modules mapped to the built-in loaders
if (systemModules.hasSplitPackages() || isPatched || haveModulePath) {
checkSplitPackages(cf, clf);
}
// load/register the modules with the built-in class loaders
loadModules(cf, clf);
Counters.add("jdk.module.boot.5.loadModulesTime", t5);
// Step 6: Define all modules to the VM
long t6 = System.nanoTime();
ModuleLayer bootLayer = ModuleLayer.empty().defineModules(cf, clf);
Counters.add("jdk.module.boot.6.layerCreateTime", t6);
// check incubating status
if (systemModules.hasIncubatorModules() || haveModulePath) {
checkIncubatingStatus(cf);
}
// --add-reads, --add-exports/--add-opens, and --illegal-access
long t7 = System.nanoTime();
addExtraReads(bootLayer);
boolean extraExportsOrOpens = addExtraExportsAndOpens(bootLayer);
addIllegalAccess(upgradeModulePath, systemModules, bootLayer, extraExportsOrOpens);
Counters.add("jdk.module.boot.7.adjustModulesTime", t7);
// save module finders for later use
if (savedModuleFinder != null) {
unlimitedFinder = new SafeModuleFinder(savedModuleFinder);
if (savedModuleFinder != finder)
limitedFinder = new SafeModuleFinder(finder);
}
// total time to initialize
Counters.add("jdk.module.boot.totalTime", t0);
Counters.publish();
return bootLayer;
}
use of java.lang.module.ModuleFinder in project Bytecoder by mirkosertic.
the class LauncherHelper method describeModule.
/**
* Called by the launcher to describe a module
*/
static void describeModule(String moduleName) {
initOutput(System.out);
ModuleFinder finder = ModuleBootstrap.limitedFinder();
ModuleReference mref = finder.find(moduleName).orElse(null);
if (mref == null) {
abort(null, "java.launcher.module.error4", moduleName);
}
ModuleDescriptor md = mref.descriptor();
// one-line summary
showModule(mref);
// unqualified exports (sorted by package)
md.exports().stream().filter(e -> !e.isQualified()).sorted(Comparator.comparing(Exports::source)).map(e -> Stream.concat(Stream.of(e.source()), toStringStream(e.modifiers())).collect(Collectors.joining(" "))).forEach(sourceAndMods -> ostream.format("exports %s%n", sourceAndMods));
// dependences
for (Requires r : md.requires()) {
String nameAndMods = Stream.concat(Stream.of(r.name()), toStringStream(r.modifiers())).collect(Collectors.joining(" "));
ostream.format("requires %s", nameAndMods);
finder.find(r.name()).map(ModuleReference::descriptor).filter(ModuleDescriptor::isAutomatic).ifPresent(any -> ostream.print(" automatic"));
ostream.println();
}
// service use and provides
for (String s : md.uses()) {
ostream.format("uses %s%n", s);
}
for (Provides ps : md.provides()) {
String names = ps.providers().stream().collect(Collectors.joining(" "));
ostream.format("provides %s with %s%n", ps.service(), names);
}
// qualified exports
for (Exports e : md.exports()) {
if (e.isQualified()) {
String who = e.targets().stream().collect(Collectors.joining(" "));
ostream.format("qualified exports %s to %s%n", e.source(), who);
}
}
// open packages
for (Opens opens : md.opens()) {
if (opens.isQualified())
ostream.print("qualified ");
String sourceAndMods = Stream.concat(Stream.of(opens.source()), toStringStream(opens.modifiers())).collect(Collectors.joining(" "));
ostream.format("opens %s", sourceAndMods);
if (opens.isQualified()) {
String who = opens.targets().stream().collect(Collectors.joining(" "));
ostream.format(" to %s", who);
}
ostream.println();
}
// non-exported/non-open packages
Set<String> concealed = new TreeSet<>(md.packages());
md.exports().stream().map(Exports::source).forEach(concealed::remove);
md.opens().stream().map(Opens::source).forEach(concealed::remove);
concealed.forEach(p -> ostream.format("contains %s%n", p));
}
Aggregations