use of java.lang.module.ResolvedModule in project Bytecoder by mirkosertic.
the class ModuleHashesBuilder method moduleToPath.
private Path moduleToPath(String name) {
ResolvedModule rm = configuration.findModule(name).orElseThrow(() -> new InternalError("Selected module " + name + " not on module path"));
URI uri = rm.reference().location().get();
Path path = Paths.get(uri);
String fn = path.getFileName().toString();
if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
}
return path;
}
use of java.lang.module.ResolvedModule 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.ResolvedModule 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.ResolvedModule in project Bytecoder by mirkosertic.
the class Loader method initRemotePackageMap.
/**
* Completes initialization of this Loader. This method populates
* remotePackageToLoader with the packages of the remote modules, where
* "remote modules" are the modules read by modules defined to this loader.
*
* @param cf the Configuration containing at least modules to be defined to
* this class loader
*
* @param parentModuleLayers the parent ModuleLayers
*/
public Loader initRemotePackageMap(Configuration cf, List<ModuleLayer> parentModuleLayers) {
for (String name : nameToModule.keySet()) {
ResolvedModule resolvedModule = cf.findModule(name).get();
assert resolvedModule.configuration() == cf;
for (ResolvedModule other : resolvedModule.reads()) {
String mn = other.name();
ClassLoader loader;
if (other.configuration() == cf) {
// loader then the packages are local.
if (pool == null) {
assert nameToModule.containsKey(mn);
continue;
}
loader = pool.loaderFor(mn);
assert loader != null;
} else {
// find the layer for the target module
ModuleLayer layer = parentModuleLayers.stream().map(parent -> findModuleLayer(parent, other.configuration())).flatMap(Optional::stream).findAny().orElseThrow(() -> new InternalError("Unable to find parent layer"));
// boot loader
assert layer.findModule(mn).isPresent();
loader = layer.findLoader(mn);
if (loader == null)
loader = ClassLoaders.platformClassLoader();
}
// find the packages that are exported to the target module
String target = resolvedModule.name();
ModuleDescriptor descriptor = other.reference().descriptor();
for (ModuleDescriptor.Exports e : descriptor.exports()) {
boolean delegate;
if (e.isQualified()) {
// qualified export in same configuration
delegate = (other.configuration() == cf) && e.targets().contains(target);
} else {
// unqualified
delegate = true;
}
if (delegate) {
String pn = e.source();
ClassLoader l = remotePackageToLoader.putIfAbsent(pn, loader);
if (l != null && l != loader) {
throw new IllegalArgumentException("Package " + pn + " cannot be imported from multiple loaders");
}
}
}
}
}
return this;
}
use of java.lang.module.ResolvedModule in project Bytecoder by mirkosertic.
the class ModuleHashesBuilder method computeHashes.
/**
* Returns a map of a module M to ModuleHashes for the modules
* that depend upon M directly or indirectly.
*
* The key for each entry in the returned map is a module M that has
* no outgoing edges to any of the candidate modules to be hashed
* i.e. M is a leaf node in a connected subgraph containing M and
* other candidate modules from the module graph filtering
* the outgoing edges from M to non-candidate modules.
*/
public Map<String, ModuleHashes> computeHashes(Set<String> roots) {
// build a graph containing the the packaged modules and
// its transitive dependences matching --hash-modules
Graph.Builder<String> builder = new Graph.Builder<>();
Deque<ResolvedModule> deque = new ArrayDeque<>(configuration.modules());
Set<ResolvedModule> visited = new HashSet<>();
while (!deque.isEmpty()) {
ResolvedModule rm = deque.pop();
if (!visited.contains(rm)) {
visited.add(rm);
builder.addNode(rm.name());
for (ResolvedModule dm : rm.reads()) {
if (!visited.contains(dm)) {
deque.push(dm);
}
builder.addEdge(rm.name(), dm.name());
}
}
}
// each node in a transposed graph is a matching packaged module
// in which the hash of the modules that depend upon it is recorded
Graph<String> transposedGraph = builder.build().transpose();
// traverse the modules in topological order that will identify
// the modules to record the hashes - it is the first matching
// module and has not been hashed during the traversal.
Set<String> mods = new HashSet<>();
Map<String, ModuleHashes> hashes = new HashMap<>();
builder.build().orderedNodes().filter(mn -> roots.contains(mn) && !mods.contains(mn)).forEach(mn -> {
// Compute hashes of the modules that depend on mn directly and
// indirectly excluding itself.
Set<String> ns = transposedGraph.dfs(mn).stream().filter(n -> !n.equals(mn) && hashModuleCandidates.contains(n)).collect(toSet());
mods.add(mn);
mods.addAll(ns);
if (!ns.isEmpty()) {
Map<String, Path> moduleToPath = ns.stream().collect(toMap(Function.identity(), this::moduleToPath));
hashes.put(mn, ModuleHashes.generate(moduleToPath, "SHA-256"));
}
});
return hashes;
}
Aggregations