Java源码示例:java.lang.module.ModuleDescriptor
示例1
/**
* Basic test of a configuration created with automatic modules
* a requires b* and c*
* b* contains p
* c* contains p
*/
@Test(expectedExceptions = { ResolutionException.class })
public void testDuplicateSuppliers1() throws IOException {
ModuleDescriptor descriptor
= ModuleDescriptor.newModule("a")
.requires("b")
.requires("c")
.build();
// c and d are automatic modules with the same package
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
// module finder locates 'a' and the modules in the directory
ModuleFinder finder
= ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
ModuleFinder.of(dir));
Configuration parent = ModuleLayer.boot().configuration();
resolve(parent, finder, "a");
}
示例2
/**
* Creates regular/modular jar files for TestClient and TestClassLoader.
*/
private static void setUp() throws Exception {
// Generate regular jar files for TestClient and TestClassLoader
JarUtils.createJarFile(CL_JAR, TEST_CLASSES,
"cl/TestClassLoader.class");
JarUtils.createJarFile(C_JAR, TEST_CLASSES,
"c/TestClient.class");
// Generate modular jar files for TestClient and TestClassLoader with
// their corresponding ModuleDescriptor.
Files.copy(CL_JAR, MCL_JAR,
StandardCopyOption.REPLACE_EXISTING);
updateModuleDescr(MCL_JAR, ModuleDescriptor.newModule("mcl")
.exports("cl").requires("java.base").build());
Files.copy(C_JAR, MC_JAR,
StandardCopyOption.REPLACE_EXISTING);
updateModuleDescr(MC_JAR, ModuleDescriptor.newModule("mc")
.exports("c").requires("java.base").requires("mcl").build());
Files.copy(C_JAR, AMC_JAR,
StandardCopyOption.REPLACE_EXISTING);
updateModuleDescr(AMC_JAR, ModuleDescriptor.newModule("mc")
.exports("c").requires("java.base").requires("cl").build());
}
示例3
/**
* 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);
}
}
}
}
示例4
/**
* Basic test to ensure that no automatic modules are resolved when
* an automatic module is not a root or required by other modules.
*/
public void testInConfiguration4() throws IOException {
ModuleDescriptor descriptor1
= ModuleDescriptor.newModule("m1")
.requires("java.base")
.build();
// automatic modules
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("auto1.jar"), "p1/C.class");
createDummyJarFile(dir.resolve("auto2.jar"), "p2/C.class");
createDummyJarFile(dir.resolve("auto3.jar"), "p3/C.class");
// module finder locates m1 and the modules in the directory
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
ModuleFinder finder2 = ModuleFinder.of(dir);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
Configuration parent = ModuleLayer.boot().configuration();
Configuration cf = resolve(parent, finder, "m1");
// ensure that no automatic module is resolved
assertTrue(cf.modules().size() == 1);
assertTrue(cf.findModule("m1").isPresent());
}
示例5
/**
* Test "uses p.S" where p is contained in a different module.
*/
@Test(expectedExceptions = { ResolutionException.class })
public void testContainsService2() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.packages(Set.of("p"))
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.requires("m1")
.uses("p.S")
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
// m2 does not read a module that exports p
resolve(finder, "m2");
}
示例6
/**
* Test that a JAR file with a Main-Class attribute results
* in a module with a main class.
*/
public void testMainClass() throws IOException {
String mainClass = "p.Main";
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
Path dir = Files.createTempDirectory(USER_DIR, "mods");
String entry = mainClass.replace('.', '/') + ".class";
createDummyJarFile(dir.resolve("m.jar"), man, entry);
ModuleFinder finder = ModuleFinder.of(dir);
Configuration parent = ModuleLayer.boot().configuration();
Configuration cf = resolve(parent, finder, "m");
ModuleDescriptor descriptor = findDescriptor(cf, "m");
assertTrue(descriptor.mainClass().isPresent());
assertEquals(descriptor.mainClass().get(), mainClass);
}
示例7
/**
* Test that a JAR file with a Main-Class attribute that is not a qualified
* type name.
*/
@Test(dataProvider = "badmainclass")
public void testBadMainClass(String mainClass, String ignore) throws IOException {
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
Path dir = Files.createTempDirectory(USER_DIR, "mods");
String entry = mainClass.replace('.', '/') + ".class";
createDummyJarFile(dir.resolve("m.jar"), man, entry);
// bad Main-Class value should be ignored
Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
assertTrue(omref.isPresent());
ModuleDescriptor descriptor = omref.get().descriptor();
assertFalse(descriptor.mainClass().isPresent());
}
示例8
/**
* Test that a JAR file with a Main-Class attribute that is not in the module
*/
public void testMissingMainClassPackage() throws IOException {
Manifest man = new Manifest();
Attributes attrs = man.getMainAttributes();
attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
attrs.put(Attributes.Name.MAIN_CLASS, "p.Main");
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createDummyJarFile(dir.resolve("m.jar"), man);
// Main-Class should be ignored because package p is not in module
Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
assertTrue(omref.isPresent());
ModuleDescriptor descriptor = omref.get().descriptor();
assertFalse(descriptor.mainClass().isPresent());
}
示例9
/**
* 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();
}
示例10
public static void main(String[] args) throws Exception {
final String MY_MODULE_NAME = "myModule";
// Verify that JVMTI reports exactly the same info as Java regarding the named modules
Asserts.assertEquals(ModuleLayer.boot().modules(), getModulesJVMTI());
// Load a new named module
ModuleDescriptor descriptor = ModuleDescriptor.newModule(MY_MODULE_NAME).build();
ModuleFinder finder = finderOf(descriptor);
ClassLoader loader = new ClassLoader() {};
Configuration parent = ModuleLayer.boot().configuration();
Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of(MY_MODULE_NAME));
ModuleLayer my = ModuleLayer.boot().defineModules(cf, m -> loader);
// Verify that the loaded module is indeed reported by JVMTI
Set<Module> jvmtiModules = getModulesJVMTI();
for (Module mod : my.modules()) {
if (!jvmtiModules.contains(mod)) {
throw new RuntimeException("JVMTI did not report the loaded named module: " + mod.getName());
}
}
}
示例11
/**
* Display JPMS information.
*/
private void displayModuleInfo() {
final StringBuilder str = new StringBuilder();
for (Module mod : new Module[] {DiceGame.class.getModule(),
DiceGameApplication.class.getModule()}) {
System.out.println("--- " + mod + " ---");
final ModuleDescriptor desc = mod.getDescriptor();
for (ModuleDescriptor.Requires r : desc.requires()) {
System.out.println(mod.getName() + " requires " + r.name());
}
System.out.println();
}
}
示例12
private void makeModule(String mn, ModuleDescriptor.Requires.Modifier mod, String... deps)
throws IOException
{
if (mod != null && mod != TRANSITIVE && mod != STATIC) {
throw new IllegalArgumentException(mod.toString());
}
StringBuilder sb = new StringBuilder();
sb.append("module " + mn + " {").append("\n");
Arrays.stream(deps).forEach(req -> {
sb.append(" requires ");
if (mod != null) {
sb.append(mod.toString().toLowerCase()).append(" ");
}
sb.append(req + ";\n");
});
sb.append("}\n");
builder.writeJavaFiles(mn, sb.toString());
compileModule(mn, srcDir);
}
示例13
private boolean matches(ModuleDescriptor md, ModuleDescriptor other) {
// build requires transitive from ModuleDescriptor
Set<ModuleDescriptor.Requires> reqTransitive = md.requires().stream()
.filter(req -> req.modifiers().contains(TRANSITIVE))
.collect(toSet());
Set<ModuleDescriptor.Requires> otherReqTransitive = other.requires().stream()
.filter(req -> req.modifiers().contains(TRANSITIVE))
.collect(toSet());
if (!reqTransitive.equals(otherReqTransitive)) {
trace("mismatch requires transitive: %s%n", reqTransitive);
return false;
}
Set<ModuleDescriptor.Requires> unused = md.requires().stream()
.filter(req -> !other.requires().contains(req))
.collect(Collectors.toSet());
if (!unused.isEmpty()) {
trace("mismatch requires: %s%n", unused);
return false;
}
return true;
}
示例14
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());
}
}
示例15
/**
* Test layers with a qualified export. The module exporting the package
* does not read the target module.
*
* m1 { exports p to m2 }
* m2 { }
*/
public void testQualifiedExports1() {
ModuleDescriptor descriptor1 = newBuilder("m1").
exports("p", Set.of("m2"))
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.build();
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf = resolve(finder1, "m1", "m2");
ClassLoader cl = new ClassLoader() { };
ModuleLayer layer = ModuleLayer.empty().defineModules(cf, mn -> cl);
assertTrue(layer.modules().size() == 2);
Module m1 = layer.findModule("m1").get();
Module m2 = layer.findModule("m2").get();
// check m1 exports p to m2
assertFalse(m1.isExported("p"));
assertTrue(m1.isExported("p", m2));
assertFalse(m1.isOpen("p", m2));
}
示例16
public void testDuplicateModule1() throws IOException {
String moduleName1 = "dupRes1Jmod1";
String moduleName2 = "dupRes1Jmod2";
List<String> classNames = Arrays.asList("java.A", "javax.B");
Path module1 = helper.generateModuleCompiledClasses(
helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName1, classNames);
Path module2 = helper.generateModuleCompiledClasses(
helper.getJmodSrcDir(), helper.getJmodClassesDir(), moduleName2, classNames);
try (OutputStream out = Files.newOutputStream(module2.resolve("module-info.class"))) {
ModuleInfoWriter.write(ModuleDescriptor.newModule(moduleName1)
.requires("java.base").build(), out);
}
Path jmod1 = JImageGenerator.getJModTask()
.addClassPath(module1)
.jmod(helper.createNewJmodFile(moduleName1))
.create()
.assertSuccess();
Path jmod2 = JImageGenerator.getJModTask()
.addClassPath(module2)
.jmod(helper.createNewJmodFile(moduleName2))
.create()
.assertSuccess();
try {
helper.generateDefaultImage(moduleName1)
.assertFailure("Error: Two versions of module dupRes1Jmod1 found in");
} finally {
deleteDirectory(jmod1);
deleteDirectory(jmod2);
}
}
示例17
private Exports exports(Set<Exports.Modifier> mods, String pn, String target) {
return ModuleDescriptor.newModule("foo")
.exports(mods, pn, Set.of(target))
.build()
.exports()
.iterator()
.next();
}
示例18
private String readModuleName(URL url) {
try (InputStream in = url.openStream()) {
ModuleDescriptor descriptor = ModuleDescriptor.read(in);
return descriptor.name();
} catch (IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
示例19
private Runtime.Version findVersion() {
final Path javaBase = assertFile(jmodsDir.resolve(JAVA_BASE_JMOD));
try (ZipFile zip = new ZipFile(javaBase.toFile())) {
final ZipEntry entry = zip.getEntry(JMOD_MODULE_INFO_PATH);
if (entry == null) {
throw new IllegalStateException("Cannot find " + JMOD_MODULE_INFO_PATH + " in " + javaBase);
}
final ModuleDescriptor descriptor = ModuleDescriptor.read(zip.getInputStream(entry));
return Runtime.Version.parse(descriptor.version()
.orElseThrow(() -> new IllegalStateException("No version in " + javaBase))
.toString());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
示例20
public void testPackagesAndMainClass2() {
Set<String> packages = ModuleDescriptor.newModule("foo")
.mainClass("p.Main")
.packages(Set.of("p"))
.build()
.packages();
assertTrue(packages.size() == 1);
assertTrue(packages.contains("p"));
}
示例21
@Test
void mergeModules() {
var sourceModule = ModuleDescriptor.newModule("a.b.c")
.requires(Set.of(ModuleDescriptor.Requires.Modifier.TRANSITIVE), "a.b.d")
.build();
var testerModule = ModuleDescriptor.newModule("a.b.c")
.requires("org.junit.jupiter.api")
.build();
var mergedModule = ModuleHelper.mergeModuleDescriptor(sourceModule, testerModule);
Assertions.assertEquals("a.b.c", mergedModule.name());
Assertions.assertTrue(mergedModule.requires().toString().contains("transitive a.b.d"));
Assertions.assertTrue(ModuleHelper.moduleDescriptorToSource(mergedModule).contains("requires transitive a.b.d;"));
}
示例22
void writeModuleInfo(Path file, ModuleDescriptor md) {
try {
Files.createDirectories(file.getParent());
try (PrintWriter pw = new PrintWriter(Files.newOutputStream(file))) {
printModuleInfo(pw, md);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
示例23
/**
* Returns true if the given module opens the given package
* unconditionally.
*
* @implNote This method currently iterates over each of the open
* packages. This will be replaced once the ModuleDescriptor.Opens
* API is updated.
*/
private boolean isOpen(ModuleReference mref, String pn) {
ModuleDescriptor descriptor = mref.descriptor();
if (descriptor.isOpen() || descriptor.isAutomatic())
return true;
for (ModuleDescriptor.Opens opens : descriptor.opens()) {
String source = opens.source();
if (!opens.isQualified() && source.equals(pn)) {
return true;
}
}
return false;
}
示例24
private void describeModule(InputStream entryInputStream, String uriString)
throws IOException
{
ModuleInfo.Attributes attrs = ModuleInfo.read(entryInputStream, null);
ModuleDescriptor md = attrs.descriptor();
ModuleTarget target = attrs.target();
ModuleHashes hashes = attrs.recordedHashes();
describeModule(md, target, hashes, uriString);
}
示例25
/**
* Creates a module layer with one module that is defined to the given class
* loader.
*/
private Module createModule(ModuleDescriptor descriptor, ClassLoader loader) {
String mn = descriptor.name();
ModuleReference mref = new ModuleReference(descriptor, null) {
@Override
public ModuleReader open() {
throw new UnsupportedOperationException();
}
};
ModuleFinder finder = new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
if (name.equals(mn)) {
return Optional.of(mref);
} else {
return Optional.empty();
}
}
@Override
public Set<ModuleReference> findAll() {
return Set.of(mref);
}
};
ModuleLayer bootLayer = ModuleLayer.boot();
Configuration cf = bootLayer.configuration()
.resolve(finder, ModuleFinder.of(), Set.of(mn));
PrivilegedAction<ModuleLayer> pa = () -> bootLayer.defineModules(cf, name -> loader);
ModuleLayer layer = AccessController.doPrivileged(pa);
Module m = layer.findModule(mn).get();
assert m.getLayer() == layer;
return m;
}
示例26
Attributes(ModuleDescriptor descriptor,
ModuleTarget target,
ModuleHashes recordedHashes,
ModuleResolution moduleResolution) {
this.descriptor = descriptor;
this.target = target;
this.recordedHashes = recordedHashes;
this.moduleResolution = moduleResolution;
}
示例27
/**
* Update regular jars and include module-info.class inside it to make
* modular jars.
*/
private static void updateModuleDescr(Path jar, ModuleDescriptor mDescr)
throws Exception {
if (mDescr != null) {
Path dir = Files.createTempDirectory("tmp");
Path mi = dir.resolve("module-info.class");
try (OutputStream out = Files.newOutputStream(mi)) {
ModuleInfoWriter.write(mDescr, out);
}
System.out.format("Adding 'module-info.class' to jar '%s'%n", jar);
JarUtils.updateJarFile(jar, dir);
}
}
示例28
/**
* Parent of configuration != configuration of parent layer
*/
@Test(expectedExceptions = { IllegalArgumentException.class })
public void testIncorrectParent1() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.requires("java.base")
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
Configuration parent = ModuleLayer.boot().configuration();
Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m1"));
ClassLoader loader = new ClassLoader() { };
ModuleLayer.empty().defineModules(cf, mn -> loader);
}
示例29
/**
* Returns a ModuleFinder that is backed by the given SystemModules object.
*
* @apiNote The returned ModuleFinder is thread safe.
*/
static ModuleFinder of(SystemModules systemModules) {
ModuleDescriptor[] descriptors = systemModules.moduleDescriptors();
ModuleTarget[] targets = systemModules.moduleTargets();
ModuleHashes[] recordedHashes = systemModules.moduleHashes();
ModuleResolution[] moduleResolutions = systemModules.moduleResolutions();
int moduleCount = descriptors.length;
ModuleReference[] mrefs = new ModuleReference[moduleCount];
@SuppressWarnings(value = {"rawtypes", "unchecked"})
Map.Entry<String, ModuleReference>[] map
= (Map.Entry<String, ModuleReference>[])new Map.Entry[moduleCount];
Map<String, byte[]> nameToHash = generateNameToHash(recordedHashes);
for (int i = 0; i < moduleCount; i++) {
String name = descriptors[i].name();
HashSupplier hashSupplier = hashSupplier(nameToHash, name);
ModuleReference mref = toModuleReference(descriptors[i],
targets[i],
recordedHashes[i],
hashSupplier,
moduleResolutions[i]);
mrefs[i] = mref;
map[i] = Map.entry(name, mref);
}
return new SystemModuleFinder(mrefs, map);
}
示例30
/**
* Basic test to detect reading two modules with the same name
*
* The test consists of three configurations:
* - Configuration cf1: m1, m2 requires transitive m1
* - Configuration cf2: m1, m3 requires transitive m1
* - Configuration cf3(cf1,cf2): m4 requires m2, m3
*/
@Test(expectedExceptions = { ResolutionException.class })
public void testReadTwoModuleWithSameName() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
.build();
ModuleDescriptor descriptor3 = newBuilder("m3")
.requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
.build();
ModuleDescriptor descriptor4 = newBuilder("m4")
.requires("m2")
.requires("m3")
.build();
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf1 = resolve(finder1, "m2");
assertTrue(cf1.modules().size() == 2);
ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3);
Configuration cf2 = resolve(finder2, "m3");
assertTrue(cf2.modules().size() == 2);
// should throw ResolutionException as m4 will read modules named "m1".
ModuleFinder finder3 = ModuleUtils.finderOf(descriptor4);
Configuration.resolve(finder3, List.of(cf1, cf2), ModuleFinder.of(), Set.of("m4"));
}