下面列出了怎么用java.lang.module.ResolvedModule的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Checks a configuration and the module-to-loader mapping to ensure that
* no two modules mapped to the same class loader have the same package.
* It also checks that no two automatic modules have the same package.
*
* @throws LayerInstantiationException
*/
private static void checkForDuplicatePkgs(Configuration cf,
Function<String, ClassLoader> clf)
{
// HashMap allows null keys
Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
ClassLoader loader = clf.apply(descriptor.name());
Set<String> loaderPackages
= loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>());
for (String pkg : descriptor.packages()) {
boolean added = loaderPackages.add(pkg);
if (!added) {
throw fail("More than one module with package %s mapped" +
" to the same class loader", pkg);
}
}
}
}
/**
* Find the runtime Module corresponding to the given ResolvedModule
* in the given parent layer (or its parents).
*/
private static Module findModule(ModuleLayer parent,
ResolvedModule resolvedModule) {
Configuration cf = resolvedModule.configuration();
String dn = resolvedModule.name();
return parent.layers()
.filter(l -> l.configuration() == cf)
.findAny()
.map(layer -> {
Optional<Module> om = layer.findModule(dn);
assert om.isPresent() : dn + " not found in layer";
Module m = om.get();
assert m.getLayer() == layer : m + " not in expected layer";
return m;
})
.orElse(null);
}
/**
* Creates a {@code Loader} in a loader pool that loads classes/resources
* from one module.
*/
public Loader(ResolvedModule resolvedModule,
LoaderPool pool,
ClassLoader parent)
{
super("Loader-" + resolvedModule.name(), parent);
this.pool = pool;
this.parent = parent;
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
String mn = descriptor.name();
this.nameToModule = Map.of(mn, mref);
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
LoadedModule lm = new LoadedModule(mref);
descriptor.packages().forEach(pn -> localPackageToModule.put(pn, lm));
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Creates a {@code Loader} that loads classes/resources from a collection
* of modules.
*
* @throws IllegalArgumentException
* If two or more modules have the same package
*/
public Loader(Collection<ResolvedModule> modules, ClassLoader parent) {
super(parent);
this.pool = null;
this.parent = parent;
Map<String, ModuleReference> nameToModule = new HashMap<>();
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
for (ResolvedModule resolvedModule : modules) {
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
nameToModule.put(descriptor.name(), mref);
descriptor.packages().forEach(pn -> {
LoadedModule lm = new LoadedModule(mref);
if (localPackageToModule.put(pn, lm) != null)
throw new IllegalArgumentException("Package "
+ pn + " in more than one module");
});
}
this.nameToModule = nameToModule;
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Creates a pool of class loaders. Each module in the given configuration
* is mapped to its own class loader in the pool. The class loader is
* created with the given parent class loader as its parent.
*/
public LoaderPool(Configuration cf,
List<ModuleLayer> parentLayers,
ClassLoader parentLoader)
{
Map<String, Loader> loaders = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
Loader loader = new Loader(resolvedModule, this, parentLoader);
String mn = resolvedModule.name();
loaders.put(mn, loader);
}
this.loaders = loaders;
// complete the initialization
loaders.values().forEach(l -> l.initRemotePackageMap(cf, parentLayers));
}
/**
* Load/register the modules to the built-in class loaders.
*/
private static void loadModules(Configuration cf,
Function<String, ClassLoader> clf) {
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
String name = resolvedModule.name();
ClassLoader loader = clf.apply(name);
if (loader == null) {
// skip java.base as it is already loaded
if (!name.equals(JAVA_BASE)) {
BootLoader.loadModule(mref);
}
} else if (loader instanceof BuiltinClassLoader) {
((BuiltinClassLoader) loader).loadModule(mref);
}
}
}
/**
* Checks for split packages between modules defined to the built-in class
* loaders.
*/
private static void checkSplitPackages(Configuration cf,
Function<String, ClassLoader> clf) {
Map<String, String> packageToModule = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
String name = descriptor.name();
ClassLoader loader = clf.apply(name);
if (loader == null || loader instanceof BuiltinClassLoader) {
for (String p : descriptor.packages()) {
String other = packageToModule.putIfAbsent(p, name);
if (other != null) {
String msg = "Package " + p + " in both module "
+ name + " and module " + other;
throw new LayerInstantiationException(msg);
}
}
}
}
}
/**
* Checks incubating status of modules in the configuration
*/
private static void checkIncubatingStatus(Configuration cf) {
String incubating = null;
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
// emit warning if the WARN_INCUBATING module resolution bit set
if (ModuleResolution.hasIncubatingWarning(mref)) {
String mn = mref.descriptor().name();
if (incubating == null) {
incubating = mn;
} else {
incubating += ", " + mn;
}
}
}
if (incubating != null)
warn("Using incubator modules: " + incubating);
}
/**
* Returns the function to map modules in the given configuration to the
* built-in class loaders.
*/
static Function<String, ClassLoader> mappingFunction(Configuration cf) {
Set<String> bootModules = bootModules();
Set<String> platformModules = platformModules();
ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
ClassLoader appClassLoader = ClassLoaders.appClassLoader();
Map<String, ClassLoader> map = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
String mn = resolvedModule.name();
if (!bootModules.contains(mn)) {
if (platformModules.contains(mn)) {
map.put(mn, platformClassLoader);
} else {
map.put(mn, appClassLoader);
}
}
}
return new Mapper(map);
}
private static Set<String> javaSE() {
String root = "java.se.ee";
ModuleFinder system = ModuleFinder.ofSystem();
if (system.find(root).isPresent()) {
return Stream.concat(Stream.of(root),
Configuration.empty().resolve(system,
ModuleFinder.of(),
Set.of(root))
.findModule(root).get()
.reads().stream()
.map(ResolvedModule::name))
.collect(toSet());
} else {
// approximation
return system.findAll().stream()
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.filter(name -> name.startsWith("java.") &&
!name.equals("java.smartcardio"))
.collect(Collectors.toSet());
}
}
ModuleTableRow(ModuleSummary ms) {
this.ms = ms;
Configuration cf = resolve(Set.of(ms.name()));
this.deps = cf.modules().stream()
.map(ResolvedModule::reference)
.map(ModuleReference::descriptor)
.collect(Collectors.toSet());
int count = (ms.numClasses() > 0 ? 1 : 0) +
(ms.numResources() > 0 ? 1 : 0) +
(ms.numConfigs() > 0 ? 1 : 0) +
(ms.numNativeLibraries() > 0 ? 1 : 0) +
(ms.numNativeLibrariesDebug() > 0 ? 1 : 0) +
(ms.numCommands() > 0 ? 1 : 0) +
(ms.numCommandsDebug() > 0 ? 1 : 0);
this.aggregator = ms.numClasses() == 1 && count == 1; // only module-info.class
// 5 fixed rows (name + 2 transitive count/size + 2 blank rows)
this.maxRows = 5 + count + (aggregator && !aggregatorNote ? 2 : 0);
}
/**
* Checks a configuration and the module-to-loader mapping to ensure that
* no two modules mapped to the same class loader have the same package.
* It also checks that no two automatic modules have the same package.
*
* @throws LayerInstantiationException
*/
private static void checkForDuplicatePkgs(Configuration cf,
Function<String, ClassLoader> clf)
{
// HashMap allows null keys
Map<ClassLoader, Set<String>> loaderToPackages = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
ClassLoader loader = clf.apply(descriptor.name());
Set<String> loaderPackages
= loaderToPackages.computeIfAbsent(loader, k -> new HashSet<>());
for (String pkg : descriptor.packages()) {
boolean added = loaderPackages.add(pkg);
if (!added) {
throw fail("More than one module with package %s mapped" +
" to the same class loader", pkg);
}
}
}
}
/**
* Find the runtime Module corresponding to the given ResolvedModule
* in the given parent layer (or its parents).
*/
private static Module findModule(ModuleLayer parent,
ResolvedModule resolvedModule) {
Configuration cf = resolvedModule.configuration();
String dn = resolvedModule.name();
return parent.layers()
.filter(l -> l.configuration() == cf)
.findAny()
.map(layer -> {
Optional<Module> om = layer.findModule(dn);
assert om.isPresent() : dn + " not found in layer";
Module m = om.get();
assert m.getLayer() == layer : m + " not in expected layer";
return m;
})
.orElse(null);
}
/**
* Creates a {@code Loader} in a loader pool that loads classes/resources
* from one module.
*/
public Loader(ResolvedModule resolvedModule,
LoaderPool pool,
ClassLoader parent)
{
super("Loader-" + resolvedModule.name(), parent);
this.pool = pool;
this.parent = parent;
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
String mn = descriptor.name();
this.nameToModule = Map.of(mn, mref);
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
LoadedModule lm = new LoadedModule(mref);
descriptor.packages().forEach(pn -> localPackageToModule.put(pn, lm));
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Creates a {@code Loader} that loads classes/resources from a collection
* of modules.
*
* @throws IllegalArgumentException
* If two or more modules have the same package
*/
public Loader(Collection<ResolvedModule> modules, ClassLoader parent) {
super(parent);
this.pool = null;
this.parent = parent;
Map<String, ModuleReference> nameToModule = new HashMap<>();
Map<String, LoadedModule> localPackageToModule = new HashMap<>();
for (ResolvedModule resolvedModule : modules) {
ModuleReference mref = resolvedModule.reference();
ModuleDescriptor descriptor = mref.descriptor();
nameToModule.put(descriptor.name(), mref);
descriptor.packages().forEach(pn -> {
LoadedModule lm = new LoadedModule(mref);
if (localPackageToModule.put(pn, lm) != null)
throw new IllegalArgumentException("Package "
+ pn + " in more than one module");
});
}
this.nameToModule = nameToModule;
this.localPackageToModule = localPackageToModule;
this.acc = AccessController.getContext();
}
/**
* Creates a pool of class loaders. Each module in the given configuration
* will be loaded its own class loader in the pool. The class loader is
* created with the given parent class loader as its parent.
*/
public LoaderPool(Configuration cf,
List<ModuleLayer> parentLayers,
ClassLoader parentLoader)
{
Map<String, Loader> loaders = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
Loader loader = new Loader(resolvedModule, this, parentLoader);
String mn = resolvedModule.name();
loaders.put(mn, loader);
}
this.loaders = loaders;
// complete the initialization
loaders.values().forEach(l -> l.initRemotePackageMap(cf, parentLayers));
}
/**
* Load/register the modules to the built-in class loaders.
*/
private static void loadModules(Configuration cf,
Function<String, ClassLoader> clf) {
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
String name = resolvedModule.name();
ClassLoader loader = clf.apply(name);
if (loader == null) {
// skip java.base as it is already loaded
if (!name.equals(JAVA_BASE)) {
BootLoader.loadModule(mref);
}
} else if (loader instanceof BuiltinClassLoader) {
((BuiltinClassLoader) loader).loadModule(mref);
}
}
}
/**
* Checks for split packages between modules defined to the built-in class
* loaders.
*/
private static void checkSplitPackages(Configuration cf,
Function<String, ClassLoader> clf) {
Map<String, String> packageToModule = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleDescriptor descriptor = resolvedModule.reference().descriptor();
String name = descriptor.name();
ClassLoader loader = clf.apply(name);
if (loader == null || loader instanceof BuiltinClassLoader) {
for (String p : descriptor.packages()) {
String other = packageToModule.putIfAbsent(p, name);
if (other != null) {
String msg = "Package " + p + " in both module "
+ name + " and module " + other;
throw new LayerInstantiationException(msg);
}
}
}
}
}
/**
* Checks incubating status of modules in the configuration
*/
private static void checkIncubatingStatus(Configuration cf) {
String incubating = null;
for (ResolvedModule resolvedModule : cf.modules()) {
ModuleReference mref = resolvedModule.reference();
// emit warning if the WARN_INCUBATING module resolution bit set
if (ModuleResolution.hasIncubatingWarning(mref)) {
String mn = mref.descriptor().name();
if (incubating == null) {
incubating = mn;
} else {
incubating += ", " + mn;
}
}
}
if (incubating != null)
warn("Using incubator modules: " + incubating);
}
/**
* Returns the function to map modules in the given configuration to the
* built-in class loaders.
*/
static Function<String, ClassLoader> mappingFunction(Configuration cf) {
Set<String> bootModules = bootModules();
Set<String> platformModules = platformModules();
ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
ClassLoader appClassLoader = ClassLoaders.appClassLoader();
Map<String, ClassLoader> map = new HashMap<>();
for (ResolvedModule resolvedModule : cf.modules()) {
String mn = resolvedModule.name();
if (!bootModules.contains(mn)) {
if (platformModules.contains(mn)) {
map.put(mn, platformClassLoader);
} else {
map.put(mn, appClassLoader);
}
}
}
return new Mapper(map);
}
public static void main(String[] args) throws Exception {
String mn = args[0];
ModuleReference mref = ModuleLayer.boot()
.configuration()
.findModule(mn)
.map(ResolvedModule::reference)
.orElseThrow(() -> new RuntimeException(mn + " not resolved!!"));
try (ModuleReader reader = mref.open()) {
reader.list().forEach(name -> {
testFindUnchecked(name);
// if the resource is a directory then find without trailing slash
if (name.endsWith("/")) {
testFindUnchecked(name.substring(0, name.length() - 1));
}
});
}
}
/**
* Basic test of "requires static":
* m1 requires static m2
* m2
* resolve m1
*/
public void testRequiresStatic2() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.requires(Set.of(Requires.Modifier.STATIC), "m2")
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf = resolve(finder, "m1");
assertTrue(cf.modules().size() == 1);
ResolvedModule m1 = cf.findModule("m1").get();
assertTrue(m1.reads().size() == 0);
}
/**
* Basic test of "requires static":
* m1 requires static m2
* m2
* resolve m1, m2
*/
public void testRequiresStatic3() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.requires(Set.of(Requires.Modifier.STATIC), "m2")
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf = resolve(finder, "m1", "m2");
assertTrue(cf.modules().size() == 2);
ResolvedModule m1 = cf.findModule("m1").get();
ResolvedModule m2 = cf.findModule("m2").get();
assertTrue(m1.reads().size() == 1);
assertTrue(m1.reads().contains(m2));
assertTrue(m2.reads().size() == 0);
}
/**
* Test the scenario where a module contains a package p and reads
* a module that also contains a package p.
*/
public void testContainsPackageInSelfAndOther() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.requires("m2")
.packages(Set.of("p"))
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.packages(Set.of("p"))
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf = resolve(finder, "m1");
assertTrue(cf.modules().size() == 2);
assertTrue(cf.findModule("m1").isPresent());
assertTrue(cf.findModule("m2").isPresent());
// m1 reads m2, m2 reads nothing
ResolvedModule m1 = cf.findModule("m1").get();
ResolvedModule m2 = cf.findModule("m2").get();
assertTrue(m1.reads().size() == 1);
assertTrue(m1.reads().contains(m2));
assertTrue(m2.reads().size() == 0);
}
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 = Path.of(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;
}
/**
* Called by the launcher to show the resolved modules
*/
static void showResolvedModules() {
initOutput(System.out);
ModuleLayer bootLayer = ModuleLayer.boot();
Configuration cf = bootLayer.configuration();
cf.modules().stream()
.map(ResolvedModule::reference)
.sorted(new JrtFirstComparator())
.forEach(LauncherHelper::showModule);
}
/**
* Returns a Graph of the given Configuration after transitive reduction.
*
* Transitive reduction of requires transitive edge and requires edge have
* to be applied separately to prevent the requires transitive edges
* (e.g. U -> V) from being reduced by a path (U -> X -> Y -> V)
* in which V would not be re-exported from U.
*/
private Graph<String> gengraph(Configuration cf) {
Graph.Builder<String> builder = new Graph.Builder<>();
cf.modules().stream()
.forEach(rm -> {
String mn = rm.name();
builder.addNode(mn);
rm.reads().stream()
.map(ResolvedModule::name)
.forEach(target -> builder.addEdge(mn, target));
});
Graph<String> rpg = requiresTransitiveGraph(cf, builder.nodes);
return builder.build().reduce(rpg);
}
static void genReport(Path outfile, Map<String, ModuleSummary> modules, Set<String> roots, String title)
throws IOException
{
Configuration cf = resolve(roots);
try (PrintStream out = new PrintStream(Files.newOutputStream(outfile))) {
HtmlDocument doc = new HtmlDocument(title, modules);
Set<ModuleDescriptor> descriptors = cf.modules().stream()
.map(ResolvedModule::reference)
.map(ModuleReference::descriptor)
.collect(Collectors.toSet());
doc.writeTo(out, descriptors);
}
}
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;
}
/**
* Called by the launcher to show the resolved modules
*/
static void showResolvedModules() {
initOutput(System.out);
ModuleLayer bootLayer = ModuleLayer.boot();
Configuration cf = bootLayer.configuration();
cf.modules().stream()
.map(ResolvedModule::reference)
.sorted(new JrtFirstComparator())
.forEach(LauncherHelper::showModule);
}