下面列出了怎么用java.lang.module.ModuleFinder的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* Test JAR file with META-INF/services configuration file with bad
* values or names.
*/
@Test(dataProvider = "badservices")
public void testBadServicesNames(String service, String provider)
throws IOException
{
Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
Path services = tmpdir.resolve("META-INF").resolve("services");
Files.createDirectories(services);
Files.write(services.resolve(service), Set.of(provider));
Path dir = Files.createTempDirectory(USER_DIR, "mods");
JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
assertTrue(omref.isPresent());
ModuleDescriptor descriptor = omref.get().descriptor();
assertTrue(descriptor.provides().isEmpty());
}
/**
* Test JAR file with META-INF/services configuration file with bad
* values or names.
*/
@Test(dataProvider = "badproviders", expectedExceptions = FindException.class)
public void testBadProviderNames(String service, String provider)
throws IOException
{
Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
// provider class
Path providerClass = tmpdir.resolve(provider.replace('.', '/') + ".class");
Files.createDirectories(providerClass.getParent());
Files.createFile(providerClass);
// services configuration file
Path services = tmpdir.resolve("META-INF").resolve("services");
Files.createDirectories(services);
Files.write(services.resolve(service), Set.of(provider));
Path dir = Files.createTempDirectory(USER_DIR, "mods");
JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
// should throw FindException
ModuleFinder.of(dir).findAll();
}
/**
* Attempt to use defineModules to create a layer with a module
* containing a package in which a type is already loaded by the class
* loader.
*/
@Test(expectedExceptions = { LayerInstantiationException.class })
public void testPackageAlreadyInUnnamedModule() throws Exception {
Class<?> c = layertest.Test.class;
assertFalse(c.getModule().isNamed()); // in unnamed module
ModuleDescriptor md = newBuilder("m")
.packages(Set.of(c.getPackageName()))
.requires("java.base")
.build();
ModuleFinder finder = ModuleUtils.finderOf(md);
Configuration parent = ModuleLayer.boot().configuration();
Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m"));
ModuleLayer.boot().defineModules(cf, mn -> c.getClassLoader());
}
/**
* Returns a ModuleFinder that only finds the given test modules
*/
static ModuleFinder finderFor(String... names) {
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
Map<String, ModuleReference> mrefs = new HashMap<>();
for (String name : names) {
Optional<ModuleReference> omref = finder.find(name);
assert omref.isPresent();
mrefs.put(name, omref.get());
}
return new ModuleFinder() {
@Override
public Optional<ModuleReference> find(String name) {
ModuleReference mref = mrefs.get(name);
return Optional.ofNullable(mref);
}
@Override
public Set<ModuleReference> findAll() {
return mrefs.values().stream().collect(Collectors.toSet());
}
};
}
/**
* Scan a JAR file or exploded module.
*/
private Optional<ModuleReference> scanModule(Path entry) {
ModuleFinder finder = ModuleFinder.of(entry);
try {
return finder.findAll().stream().findFirst();
} catch (FindException e) {
ostream.println(entry);
ostream.println(INDENT + e.getMessage());
Throwable cause = e.getCause();
if (cause != null) {
ostream.println(INDENT + cause);
}
errorFound = true;
return Optional.empty();
}
}
/**
* Test JAR file with META-INF/services configuration file listing a
* provider that is not in the module.
*/
@Test(expectedExceptions = FindException.class)
public void testMissingProviderPackage() throws IOException {
Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
// services configuration file
Path services = tmpdir.resolve("META-INF").resolve("services");
Files.createDirectories(services);
Files.write(services.resolve("p.S"), Set.of("q.P"));
Path dir = Files.createTempDirectory(USER_DIR, "mods");
JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
// should throw FindException
ModuleFinder.of(dir).findAll();
}
/**
* Basic test to detect reading a module with the same name as itself
*
* The test consists of three configurations:
* - Configuration cf1: m1, m2 requires transitive m1
* - Configuration cf2: m1 requires m2
*/
@Test(expectedExceptions = { ResolutionException.class })
public void testReadModuleWithSameNameAsSelf() {
ModuleDescriptor descriptor1_v1 = newBuilder("m1")
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
.build();
ModuleDescriptor descriptor1_v2 = newBuilder("m1")
.requires("m2")
.build();
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1_v1, descriptor2);
Configuration cf1 = resolve(finder1, "m2");
assertTrue(cf1.modules().size() == 2);
// resolve should throw ResolutionException
ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1_v2);
resolve(cf1, finder2, "m1");
}
/**
* Exercise defineModules with a configuration with a module that
* contains a package that is the same name as a non-exported package in
* a parent layer.
*/
public void testContainsSamePackageAsBootLayer() {
// check assumption that java.base contains sun.launcher
ModuleDescriptor base = Object.class.getModule().getDescriptor();
assertTrue(base.packages().contains("sun.launcher"));
ModuleDescriptor descriptor = newBuilder("m1")
.requires("java.base")
.packages(Set.of("sun.launcher"))
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor);
Configuration parent = ModuleLayer.boot().configuration();
Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m1"));
assertTrue(cf.modules().size() == 1);
ClassLoader loader = new ClassLoader() { };
ModuleLayer layer = ModuleLayer.boot().defineModules(cf, mn -> loader);
assertTrue(layer.modules().size() == 1);
}
/**
* Test ModuleFinder with an exploded module containing a mix of class
* and non-class resources
*/
public void testOfOneExplodedModuleWithResources() throws Exception {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
Path m_dir = createExplodedModule(dir.resolve("m"), "m",
"LICENSE",
"README",
"WEB-INF/tags",
"p/Type.class",
"p/resources/m.properties",
"q-/Type.class", // not a legal package name
"q-/resources/m/properties");
ModuleFinder finder = ModuleFinder.of(m_dir);
Optional<ModuleReference> mref = finder.find("m");
assertTrue(mref.isPresent(), "m not found");
ModuleDescriptor descriptor = mref.get().descriptor();
assertTrue(descriptor.packages().size() == 2);
assertTrue(descriptor.packages().contains("p"));
assertTrue(descriptor.packages().contains("p.resources"));
}
/**
* Test ModuleFinder.of with a directory containing hidden files
*/
public void testOfWithHiddenFiles() throws Exception {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createExplodedModule(dir.resolve("m"), "m",
"com/.ignore",
"com/foo/.ignore",
"com/foo/foo.properties");
ModuleFinder finder = ModuleFinder.of(dir);
ModuleReference mref = finder.find("m").orElse(null);
assertNotNull(mref);
Set<String> expectedPackages;
if (System.getProperty("os.name").startsWith("Windows")) {
expectedPackages = Set.of("com", "com.foo");
} else {
expectedPackages = Set.of("com.foo");
}
assertEquals(mref.descriptor().packages(), expectedPackages);
}
/**
* Test ModuleFinder.of with a file path to a directory containing a file
* that will not be recognized as a module.
*/
public void testOfWithUnrecognizedEntryInDirectory2() throws Exception {
Path dir = Files.createTempDirectory(USER_DIR, "mods");
createModularJar(dir.resolve("m1.jar"), "m1");
Files.createTempFile(dir, "m2", ".junk");
ModuleFinder finder = ModuleFinder.of(dir);
assertTrue(finder.find("m1").isPresent());
assertFalse(finder.find("m2").isPresent());
finder = ModuleFinder.of(dir);
assertTrue(finder.findAll().size() == 1);
}
public static void main(String... args) throws Exception {
ModuleFinder afterFinder = ModuleFinder.of(Paths.get("mods"));
Configuration cf = ModuleLayer.boot().configuration()
.resolveAndBind(ModuleFinder.of(), afterFinder,
List.of("m1", "m2"));
System.out.println("Configuration: " + cf);
ModuleLayer l = ModuleLayer.defineModulesWithManyLoaders(cf,
List.of(ModuleLayer.boot()),
ClassLoader.getPlatformClassLoader())
.layer();
Module m1 = l.findModule("m1").get();
ResourceBundle bundle =
ResourceBundle.getBundle("p.resources.MyResource",
Locale.US, m1);
ResourceBundle jabundle =
ResourceBundle.getBundle("p.resources.MyResource",
Locale.JAPANESE, m1);
String enResult = bundle.getString("key");
String jaResult = jabundle.getString("key");
if (!"hi".equals(enResult) || !"ja".equals(jaResult)) {
throw new RuntimeException("Unexpected resources loaded: en: " +
enResult + ", ja: " + jaResult);
}
Class<?> c = Class.forName(m1, "p.Main");
Method m = c.getDeclaredMethod("run");
m.invoke(null);
}
/**
* Test a multi-release JAR with a module-info.class in the versioned
* section of the JAR.
*/
public void testModuleInfoInVersionedSection() throws Exception {
String name = "m1";
ModuleDescriptor descriptor1 = ModuleDescriptor.newModule(name)
.requires("java.base")
.build();
// module descriptor for versioned section
ModuleDescriptor descriptor2 = ModuleDescriptor.newModule(name)
.requires("java.base")
.requires("jdk.unsupported")
.build();
Path jar = new JarBuilder(name)
.moduleInfo(MODULE_INFO, descriptor1)
.resource("p/Main.class")
.resource("p/Helper.class")
.moduleInfo("META-INF/versions/" + VERSION + "/" + MODULE_INFO, descriptor2)
.resource("META-INF/versions/" + VERSION + "/p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")
.build();
// find the module
ModuleFinder finder = ModuleFinder.of(jar);
Optional<ModuleReference> omref = finder.find(name);
assertTrue((omref.isPresent()));
ModuleReference mref = omref.get();
// ensure that the right module-info.class is loaded
ModuleDescriptor descriptor = mref.descriptor();
assertEquals(descriptor.name(), name);
if (MULTI_RELEASE) {
assertEquals(descriptor.requires(), descriptor2.requires());
} else {
assertEquals(descriptor.requires(), descriptor1.requires());
}
}
/**
* Returns the ModuleFinder for the initial configuration.
*
* @apiNote Used to support "{@code java --list-modules}".
*/
public static ModuleFinder limitedFinder() {
ModuleFinder finder = limitedFinder;
if (finder == null) {
return unlimitedFinder();
} else {
return finder;
}
}
/**
* Test "provides p.S" where p is contained in the same module.
*/
public void testContainsService3() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.packages(Set.of("p", "q"))
.provides("p.S", List.of("q.S1"))
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
Configuration cf = resolve(finder, "m1");
assertTrue(cf.modules().size() == 1);
assertTrue(cf.findModule("m1").isPresent());
}
/**
* Basic test of a multi-release JAR.
*/
public void testBasic() throws Exception {
String name = "m1";
ModuleDescriptor descriptor = ModuleDescriptor.newModule(name)
.requires("java.base")
.build();
Path jar = new JarBuilder(name)
.moduleInfo("module-info.class", descriptor)
.resource("p/Main.class")
.resource("p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")
.build();
// find the module
ModuleFinder finder = ModuleFinder.of(jar);
Optional<ModuleReference> omref = finder.find(name);
assertTrue((omref.isPresent()));
ModuleReference mref = omref.get();
// check module packages
descriptor = mref.descriptor();
Set<String> packages = descriptor.packages();
assertTrue(packages.contains("p"));
if (MULTI_RELEASE) {
assertTrue(packages.size() == 2);
assertTrue(packages.contains("p.internal"));
} else {
assertTrue(packages.size() == 1);
}
}
@Test
public void testSystemModules() {
Path jimage = Paths.get(System.getProperty("java.home"), "lib", "modules");
if (Files.notExists(jimage))
return;
ModuleFinder.ofSystem().findAll().stream()
.forEach(this::checkAttributes);
}
/**
* Test proxy implementing interfaces in a Layer and defined in a
* dynamic module
*/
@Test
public void testProxyInDynamicModule() throws Exception {
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
ModuleLayer bootLayer = ModuleLayer.boot();
Configuration cf = bootLayer
.configuration()
.resolveAndBind(ModuleFinder.of(), finder, Arrays.asList(modules));
ClassLoader scl = ClassLoader.getSystemClassLoader();
ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl);
ClassLoader loader = layer.findLoader("m1");
assertTrue(layer.findModule("m1").isPresent());
assertTrue(layer.findModule("m2").isPresent());
assertTrue(layer.findModule("m3").isPresent());
Class<?>[] interfaces = new Class<?>[] {
Class.forName("p.one.internal.J", false, loader),
};
Object o = Proxy.newProxyInstance(loader, interfaces, handler);
Class<?> proxyClass = o.getClass();
Package pkg = proxyClass.getPackage();
assertTrue(proxyClass.getModule().isNamed());
assertTrue(pkg.isSealed());
assertEquals(proxyClass.getModule().getLayer(), null);
}
/**
* Test the scenario where a module that exports a package that is also
* exported by a module that it reads in a parent layer.
*/
@Test(expectedExceptions = { ResolutionException.class })
public void testExportSamePackageAsBootLayer() {
ModuleDescriptor descriptor = newBuilder("m1")
.requires("java.base")
.exports("java.lang")
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor);
Configuration bootConfiguration = ModuleLayer.boot().configuration();
// m1 contains package java.lang, java.base exports package java.lang to m1
resolve(bootConfiguration, finder, "m1");
}
private static ClassLoader createModuleLoader(final ClassLoader cl,
final String modulePath, final String addModules) {
if (addModules == null) {
throw new IllegalArgumentException("--module-path specified with no --add-modules");
}
final Path[] paths = Stream.of(modulePath.split(File.pathSeparator)).
map(s -> Paths.get(s)).
toArray(sz -> new Path[sz]);
final ModuleFinder mf = ModuleFinder.of(paths);
final Set<ModuleReference> mrefs = mf.findAll();
if (mrefs.isEmpty()) {
throw new RuntimeException("No modules in script --module-path: " + modulePath);
}
final Set<String> rootMods;
if (addModules.equals("ALL-MODULE-PATH")) {
rootMods = mrefs.stream().
map(mr->mr.descriptor().name()).
collect(Collectors.toSet());
} else {
rootMods = Stream.of(addModules.split(",")).
map(String::trim).
collect(Collectors.toSet());
}
final ModuleLayer boot = ModuleLayer.boot();
final Configuration conf = boot.configuration().
resolve(mf, ModuleFinder.of(), rootMods);
final String firstMod = rootMods.iterator().next();
return boot.defineModulesWithOneLoader(conf, cl).findLoader(firstMod);
}
/**
* Basic test of "requires static":
* The test consists of three configurations:
* - Configuration cf1: m1
* - Configuration cf2: m3 requires m1, requires static m2
*/
public void testRequiresStatic6() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.build();
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
Configuration cf1 = resolve(finder1, "m1");
assertTrue(cf1.modules().size() == 1);
assertTrue(cf1.findModule("m1").isPresent());
ModuleDescriptor descriptor3 = newBuilder("m3")
.requires("m1")
.requires(Set.of(Requires.Modifier.STATIC), "m2")
.build();
ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
Configuration cf2 = resolve(cf1, finder2, "m3");
assertTrue(cf2.modules().size() == 1);
assertTrue(cf2.findModule("m3").isPresent());
ResolvedModule m1 = cf1.findModule("m1").get();
ResolvedModule m3 = cf2.findModule("m3").get();
assertTrue(m3.reads().size() == 1);
assertTrue(m3.reads().contains(m1));
}
private static Stream<Provider<Plugin>> findDynamicPlugins(Path path) {
var finder = ModuleFinder.of(path);
var moduleNames = finder.findAll().stream().map(ref -> ref.descriptor().name()).collect(toUnmodifiableSet());
var boot = ModuleLayer.boot();
var cf = boot.configuration().resolve(finder, ModuleFinder.of(), moduleNames);
var classLoader = new ClassLoader(Plugins.class.getClassLoader()) { /* empty */ };
var layer = boot.defineModulesWithOneLoader(cf, classLoader);
var serviceLoader = ServiceLoader.load(layer, Plugin.class);
return serviceLoader.stream();
}
/**
* Basic test of using the beforeFinder to override a module in a parent
* configuration.
*/
public void testOverriding1() {
ModuleDescriptor descriptor1 = newBuilder("m1").build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
Configuration cf1 = resolve(finder, "m1");
assertTrue(cf1.modules().size() == 1);
assertTrue(cf1.findModule("m1").isPresent());
Configuration cf2 = resolve(cf1, finder, "m1");
assertTrue(cf2.modules().size() == 1);
assertTrue(cf2.findModule("m1").isPresent());
}
/**
* Basic test of binding services
* m1 uses p.S
* m2 provides p.S
*/
public void testServiceBinding1() {
ModuleDescriptor descriptor1 = newBuilder("m1")
.exports("p")
.uses("p.S")
.build();
ModuleDescriptor descriptor2 = newBuilder("m2")
.requires("m1")
.provides("p.S", List.of("q.T"))
.build();
ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf = resolveAndBind(finder, "m1");
assertTrue(cf.modules().size() == 2);
assertTrue(cf.findModule("m1").isPresent());
assertTrue(cf.findModule("m2").isPresent());
assertTrue(cf.parents().size() == 1);
assertTrue(cf.parents().get(0) == Configuration.empty());
ResolvedModule m1 = cf.findModule("m1").get();
ResolvedModule m2 = cf.findModule("m2").get();
assertTrue(m1.configuration() == cf);
assertTrue(m1.reads().size() == 0);
assertTrue(m2.configuration() == cf);
assertTrue(m2.reads().size() == 1);
assertTrue(m2.reads().contains(m1));
}
/**
* Test ModuleFinder.compose with two module finders
*/
public void testComposeOfTwo() throws Exception {
Path dir1 = Files.createTempDirectory(USER_DIR, "mods1");
createModularJar(dir1.resolve("m1.jar"), "[email protected]");
createModularJar(dir1.resolve("m2.jar"), "[email protected]");
Path dir2 = Files.createTempDirectory(USER_DIR, "mods2");
createModularJar(dir2.resolve("m1.jar"), "[email protected]");
createModularJar(dir2.resolve("m2.jar"), "[email protected]");
createModularJar(dir2.resolve("m3.jar"), "m3");
createModularJar(dir2.resolve("m4.jar"), "m4");
ModuleFinder finder1 = ModuleFinder.of(dir1);
ModuleFinder finder2 = ModuleFinder.of(dir2);
ModuleFinder finder = ModuleFinder.compose(finder1, finder2);
assertTrue(finder.findAll().size() == 4);
assertTrue(finder.find("m1").isPresent());
assertTrue(finder.find("m2").isPresent());
assertTrue(finder.find("m3").isPresent());
assertTrue(finder.find("m4").isPresent());
assertFalse(finder.find("java.rhubarb").isPresent());
// check that [email protected] is found
ModuleDescriptor m1 = finder.find("m1").get().descriptor();
assertEquals(m1.version().get().toString(), "1.0");
// check that [email protected] is found
ModuleDescriptor m2 = finder.find("m2").get().descriptor();
assertEquals(m2.version().get().toString(), "1.0");
}
@Override
public UrlSource resolveClassPath() {
Iterable<URL> classpath = UrlSource.From.classPathSystemProperties();
Iterable<URL> modulepath = ModuleFinder.ofSystem().findAll().stream()
.flatMap(moduleReference -> moduleReference.location().stream())
.map(this::toUrl)
.collect(toList());
return UrlSource.From.iterable(concat(classpath, modulepath));
}
/**
* Return the system modules currently installed.
* This filter out modules that do not starts with java.* or jdk.*.
* @return the system modules currently installed.
*/
public static ModuleFinder systemModulesFinder() {
return filter(ModuleFinder.ofSystem(), ref -> {
var moduleName = ref.descriptor().name();
return moduleName.startsWith("java.") || moduleName.startsWith("jdk.");
});
}
/**
* Test multi-release JAR as an automatic module.
*/
public void testAutomaticModule() throws Exception {
String name = "m";
Path jar = new JarBuilder(name)
.resource("p/Main.class")
.resource("p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/Helper.class")
.resource("META-INF/versions/" + VERSION + "/p/internal/Helper.class")
.build();
// find the module
ModuleFinder finder = ModuleFinder.of(jar);
Optional<ModuleReference> omref = finder.find(name);
assertTrue((omref.isPresent()));
ModuleReference mref = omref.get();
// check module packages
ModuleDescriptor descriptor = mref.descriptor();
Set<String> packages = descriptor.packages();
if (MULTI_RELEASE) {
assertTrue(packages.size() == 2);
assertTrue(packages.contains("p.internal"));
} else {
assertTrue(packages.size() == 1);
}
}
/**
* Test layers with a qualified export. The module exporting the package
* does not read the target module.
*
* - Configuration/layer1: m1
* - Configuration/layer2: m1, m2 { exports p to m1; }
*/
public void testQualifiedExports5() {
// create layer1 with m1
ModuleDescriptor descriptor1 = newBuilder("m1").build();
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
Configuration cf1 = resolve(finder1, "m1");
ClassLoader cl1 = new ClassLoader() { };
ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1);
assertTrue(layer1.modules().size() == 1);
// create layer2 with m1 and m2
ModuleDescriptor descriptor2 = newBuilder("m2").exports("p", Set.of("m1")).build();
ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor2);
Configuration cf2 = resolve(cf1, finder2, "m1", "m2");
ClassLoader cl2 = new ClassLoader() { };
ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2);
assertTrue(layer2.modules().size() == 2);
Module m1_v1 = layer1.findModule("m1").get();
Module m1_v2 = layer2.findModule("m1").get();
Module m2 = layer2.findModule("m2").get();
// check m2 exports p to layer2/m2
assertFalse(m2.isExported("p"));
assertTrue(m2.isExported("p", m1_v2));
assertFalse(m2.isExported("p", m1_v1));
}
private static List<ModuleReference> modules(List<Path> paths) {
return ModuleFinder.of(paths.toArray(Path[]::new))
.findAll()
.stream()
.filter(ref -> ref.location().isPresent())
.sorted(Comparator.comparing(ref -> ref.descriptor().name()))
.collect(toUnmodifiableList());
}