|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package jdk.internal.module; |
|
|
|
import java.io.PrintStream; |
|
import java.lang.module.Configuration; |
|
import java.lang.module.ModuleDescriptor; |
|
import java.lang.module.ModuleFinder; |
|
import java.lang.module.ModuleReference; |
|
import java.lang.module.ResolvedModule; |
|
import java.net.URI; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.Collection; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.Optional; |
|
import java.util.Set; |
|
import java.util.function.Function; |
|
import java.util.stream.Collectors; |
|
|
|
import jdk.internal.access.JavaLangModuleAccess; |
|
import jdk.internal.loader.BootLoader; |
|
import jdk.internal.loader.BuiltinClassLoader; |
|
import jdk.internal.loader.ClassLoaders; |
|
import jdk.internal.access.JavaLangAccess; |
|
import jdk.internal.access.SharedSecrets; |
|
|
|
/** |
|
* A helper class for creating and updating modules. This class is intended to |
|
* support command-line options, tests, and the instrumentation API. It is also |
|
* used by the VM to load modules or add read edges when agents are instrumenting |
|
* code that need to link to supporting classes. |
|
* |
|
* The parameters that are package names in this API are the fully-qualified |
|
* names of the packages as defined in section 6.5.3 of <cite>The Java |
|
* Language Specification </cite>, for example, {@code "java.lang"}. |
|
*/ |
|
|
|
public class Modules { |
|
private Modules() { } |
|
|
|
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); |
|
private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Module defineModule(ClassLoader loader, |
|
ModuleDescriptor descriptor, |
|
URI uri) |
|
{ |
|
return JLA.defineModule(loader, descriptor, uri); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void addReads(Module m1, Module m2) { |
|
JLA.addReads(m1, m2); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void addReadsAllUnnamed(Module m) { |
|
JLA.addReadsAllUnnamed(m); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void addExports(Module m1, String pn, Module m2) { |
|
JLA.addExports(m1, pn, m2); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void addExports(Module m, String pn) { |
|
JLA.addExports(m, pn); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void addExportsToAllUnnamed(Module m, String pn) { |
|
JLA.addExportsToAllUnnamed(m, pn); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void addOpens(Module m1, String pn, Module m2) { |
|
JLA.addOpens(m1, pn, m2); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void addOpensToAllUnnamed(Module m, String pn) { |
|
JLA.addOpensToAllUnnamed(m, pn); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public static void addUses(Module m, Class<?> service) { |
|
JLA.addUses(m, service); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public static void addProvides(Module m, Class<?> service, Class<?> impl) { |
|
ModuleLayer layer = m.getLayer(); |
|
|
|
PrivilegedAction<ClassLoader> pa = m::getClassLoader; |
|
@SuppressWarnings("removal") |
|
ClassLoader loader = AccessController.doPrivileged(pa); |
|
|
|
ClassLoader platformClassLoader = ClassLoaders.platformClassLoader(); |
|
if (layer == null || loader == null || loader == platformClassLoader) { |
|
|
|
ServicesCatalog catalog; |
|
if (loader == null) { |
|
catalog = BootLoader.getServicesCatalog(); |
|
} else { |
|
catalog = ServicesCatalog.getServicesCatalog(loader); |
|
} |
|
catalog.addProvider(m, service, impl); |
|
} |
|
|
|
if (layer != null) { |
|
|
|
JLA.getServicesCatalog(layer).addProvider(m, service, impl); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Configuration newBootLayerConfiguration(ModuleFinder finder, |
|
Collection<String> roots, |
|
PrintStream traceOutput) |
|
{ |
|
return JLMA.resolveAndBind(finder, roots, traceOutput); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void transformedByAgent(Module m) { |
|
addReads(m, BootLoader.getUnnamedModule()); |
|
addReads(m, ClassLoaders.appClassLoader().getUnnamedModule()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
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) { |
|
|
|
return module; |
|
} |
|
|
|
|
|
ModuleFinder empty = ModuleFinder.of(); |
|
ModuleFinder finder = ModuleBootstrap.unlimitedFinder(); |
|
Set<String> roots = Set.of(name); |
|
Configuration cf = top.configuration().resolveAndBind(empty, finder, roots); |
|
|
|
|
|
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf); |
|
ModuleLayer newLayer = top.defineModules(cf, clf); |
|
|
|
|
|
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()) { |
|
|
|
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); |
|
}})); |
|
|
|
|
|
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); |
|
} |
|
|
|
|
|
JLA.addNonExportedPackages(newLayer); |
|
|
|
|
|
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); |
|
} |
|
} |
|
|
|
|
|
topLayer = newLayer; |
|
|
|
|
|
return newLayer.findModule(name) |
|
.orElseThrow(() -> new InternalError("module not loaded")); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Optional<Module> findLoadedModule(String name) { |
|
ModuleLayer top = topLayer; |
|
if (top == null) |
|
top = ModuleLayer.boot(); |
|
return top.findModule(name); |
|
} |
|
|
|
|
|
private static volatile ModuleLayer topLayer; |
|
|
|
} |