/** * Test unnamed module has no access to other proxy interface */ @Test public void testNoReadAccess() throws Exception { ModuleFinder finder = ModuleFinder.of(MODS_DIR); ModuleLayer bootLayer = ModuleLayer.boot(); Configuration cf = bootLayer .configuration() .resolveAndBind(ModuleFinder.of(), finder, modules); ClassLoader parentLoader = this.getClass().getClassLoader(); ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, parentLoader); ClassLoader loader = layer.findLoader("m1"); Class<?>[] interfaces = new Class<?>[] { Class.forName("p.one.I", false, loader), Class.forName("q.NP", false, loader) // non-public interface in unnamed module }; checkIAE(loader, interfaces); }
/** * Basic test of a configuration created with automatic modules * a contains p, requires b* * b* contains p */ @Test(expectedExceptions = { ResolutionException.class }) public void testDuplicateSuppliers2() throws IOException { ModuleDescriptor descriptor = ModuleDescriptor.newModule("a") .packages(Set.of("p")) .requires("b") .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"); // 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"); }
/** * Generate dotfile of the given path */ public void genDotFile(Path path, String name, Configuration configuration, Attributes attributes) throws IOException { // transitive reduction Graph<String> graph = apiOnly ? requiresTransitiveGraph(configuration, Set.of(name)) : gengraph(configuration); DotGraphBuilder builder = new DotGraphBuilder(name, graph, attributes); builder.subgraph("se", "java", attributes.javaSubgraphColor(), DotGraphBuilder.JAVA_SE_SUBGRAPH) .subgraph("jdk", "jdk", attributes.jdkSubgraphColor(), DotGraphBuilder.JDK_SUBGRAPH) .modules(graph.nodes().stream() .map(mn -> configuration.findModule(mn).get() .reference().descriptor())); // build dot file builder.build(path); }
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()); } }
/** * 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); }
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); }
/** * Creates a new module layer from the modules in the given configuration. */ private ModuleLayer(Configuration cf, List<ModuleLayer> parents, Function<String, ClassLoader> clf) { this.cf = cf; this.parents = parents; // no need to do defensive copy Map<String, Module> map; if (parents.isEmpty()) { map = Collections.emptyMap(); } else { map = Module.defineModules(cf, clf, this); } this.nameToModule = map; // no need to do defensive copy }
/** * Checks that the parent configurations match the configuration of * the parent layers. */ private static void checkConfiguration(Configuration cf, List<ModuleLayer> parentLayers) { Objects.requireNonNull(cf); List<Configuration> parentConfigurations = cf.parents(); if (parentLayers.size() != parentConfigurations.size()) throw new IllegalArgumentException("wrong number of parents"); int index = 0; for (ModuleLayer parent : parentLayers) { if (parent.configuration() != parentConfigurations.get(index)) { throw new IllegalArgumentException( "Parent of configuration != configuration of this Layer"); } index++; } }
/** * Test defineModulesWithXXX when modules that have overlapping packages. * * Test scenario: * m1 exports p * m2 exports p */ public void testOverlappingPackages() { ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1").exports("p").build(); ModuleDescriptor descriptor2 = ModuleDescriptor.newModule("m2").exports("p").build(); ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf = ModuleLayer.boot() .configuration() .resolve(finder, ModuleFinder.of(), Set.of("m1", "m2")); // cannot define both module m1 and m2 to the same class loader try { ModuleLayer.boot().defineModulesWithOneLoader(cf, null); assertTrue(false); } catch (LayerInstantiationException expected) { } // should be okay to have one module per class loader ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null); checkLayer(layer, "m1", "m2"); }
/** * Exercise ModuleLayer.empty() */ public void testEmpty() { ModuleLayer emptyLayer = ModuleLayer.empty(); assertTrue(emptyLayer.parents().isEmpty()); assertTrue(emptyLayer.configuration() == Configuration.empty()); assertTrue(emptyLayer.modules().isEmpty()); assertFalse(emptyLayer.findModule("java.base").isPresent()); try { emptyLayer.findLoader("java.base"); assertTrue(false); } catch (IllegalArgumentException expected) { } }
/** * Test layers with a qualified export. The module exporting the package * reads the target module. * * m1 { exports p to m2; } * m2 { requires m1; } */ public void testQualifiedExports2() { ModuleDescriptor descriptor1 = newBuilder("m1") .exports("p", Set.of("m2")) .build(); ModuleDescriptor descriptor2 = newBuilder("m2") .requires("m1") .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); Configuration cf = resolve(finder1, "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)); }
/** * 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); } } } } }
/** * Basic test of ModuleLayer.defineModulesWithOneLoader * * Test scenario: * m1 requires m2 and m3 */ public void testWithOneLoader() throws Exception { Configuration cf = resolve("m1"); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); checkLayer(layer, "m1", "m2", "m3"); ClassLoader cl1 = layer.findLoader("m1"); ClassLoader cl2 = layer.findLoader("m2"); ClassLoader cl3 = layer.findLoader("m3"); assertTrue(cl1.getParent() == scl); assertTrue(cl2 == cl1); assertTrue(cl3 == cl1); invoke(layer, "m1", "p.Main"); }
/** * Test creating a configuration containing platform specific modules. */ @Test(dataProvider = "platformmatch") public void testPlatformMatch(String s1, String s2) throws IOException { ModuleDescriptor base = ModuleDescriptor.newModule("java.base").build(); Path system = writeModule(base, null); ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1") .requires("m2") .build(); Path dir1 = writeModule(descriptor1, s1); ModuleDescriptor descriptor2 = ModuleDescriptor.newModule("m2").build(); Path dir2 = writeModule(descriptor2, s2); ModuleFinder finder = ModuleFinder.of(system, dir1, dir2); Configuration cf = resolve(finder, "m1"); assertTrue(cf.modules().size() == 3); assertTrue(cf.findModule("java.base").isPresent()); assertTrue(cf.findModule("m1").isPresent()); assertTrue(cf.findModule("m2").isPresent()); }
/** * 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); }
static ModuleLayer createPluginsLayer(List<Path> paths) { Path[] dirs = paths.toArray(new Path[0]); ModuleFinder finder = ModulePath.of(Runtime.version(), true, dirs); Configuration bootConfiguration = ModuleLayer.boot().configuration(); try { Configuration cf = bootConfiguration .resolveAndBind(ModuleFinder.of(), finder, Collections.emptySet()); ClassLoader scl = ClassLoader.getSystemClassLoader(); return ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); } catch (Exception ex) { // Malformed plugin modules (e.g.: same package in multiple modules). throw new PluginException("Invalid modules in the plugins path: " + ex); } }
@Test public void test() throws Exception { ModuleFinder empty = ModuleFinder.of(); ModuleFinder finder = ModuleFinder.of(MODS_DIR); ModuleLayer bootLayer = ModuleLayer.boot(); Configuration cf0 = bootLayer.configuration(); Configuration cf1 = cf0.resolveAndBind(finder, empty, Set.of("s1", "s2")); Configuration cf2 = cf1.resolveAndBind(finder, empty, Set.of("s1", "s2")); // cf1 contains s1, p1, s2, p2 assertTrue(cf1.modules().size() == 4); // cf1 contains s1, p1, s2, p2 assertTrue(cf2.modules().size() == 4); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer1 = bootLayer.defineModulesWithManyLoaders(cf1, scl); testLayer(layer1); ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, scl); testLayer(layer2); }
/** * 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)); }
/** * 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(dataProvider = "platformmatch") public void testResolveRequiresWithCompatibleParents(String s1, String s2) throws IOException { ModuleDescriptor base = ModuleDescriptor.newModule("java.base").build(); Path system = writeModule(base, null); ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1").build(); Path dir1 = writeModule(descriptor1, s1); ModuleDescriptor descriptor2 = ModuleDescriptor.newModule("m2").build(); Path dir2 = writeModule(descriptor2, s2); ModuleFinder finder1 = ModuleFinder.of(system, dir1); Configuration cf1 = resolve(finder1, "m1"); ModuleFinder finder2 = ModuleFinder.of(system, dir2); Configuration cf2 = resolve(finder2, "m2"); Configuration cf3 = Configuration.resolve(ModuleFinder.of(), List.of(cf1, cf2), ModuleFinder.of(), Set.of()); assertTrue(cf3.parents().size() == 2); }
/** * Creates a child layer with m1 and m2, invokes m1/p.Main to ensure that * classes can be loaded. */ private void loadAndRunModule(ModuleFinder finder) throws Exception { ModuleLayer bootLayer = ModuleLayer.boot(); Configuration cf = bootLayer.configuration() .resolve(finder, ModuleFinder.of(), Set.of("m1")); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl); Class<?> c = layer.findLoader("m1").loadClass("p.Main"); Method m = c.getMethod("main", String[].class); m.invoke(null, (Object)new String[0]); }
/** * Basic test of ServiceLoader.load where the service provider module is an * automatic module. */ @Test public void testWithAutomaticModule() throws Exception { Path here = Paths.get(""); Path jar = Files.createTempDirectory(here, "lib").resolve("pearscript.jar"); Path classes = Paths.get(System.getProperty("test.classes")); JarUtils.createJarFile(jar, classes, "META-INF", "org"); ModuleFinder finder = ModuleFinder.of(jar); ModuleLayer bootLayer = ModuleLayer.boot(); Configuration parent = bootLayer.configuration(); Configuration cf = parent.resolveAndBind(finder, ModuleFinder.of(), Set.of()); assertTrue(cf.modules().size() == 1); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, scl); assertTrue(layer.modules().size() == 1); ClassLoader loader = layer.findLoader("pearscript"); ScriptEngineFactory factory; // load using the class loader as context factory = ServiceLoader.load(ScriptEngineFactory.class, loader) .findFirst() .orElse(null); assertNotNull(factory); assertTrue(factory.getClass().getClassLoader() == loader); // load using the layer as context factory = ServiceLoader.load(layer, ScriptEngineFactory.class) .findFirst() .orElse(null); assertNotNull(factory); assertTrue(factory.getClass().getClassLoader() == loader); }
/** * Returns the directory for the given module (by name). */ static Path directoryFor(String name) { Configuration cf = ModuleLayer.boot().configuration(); ResolvedModule resolvedModule = cf.findModule(name).orElse(null); if (resolvedModule == null) throw new RuntimeException("not found: " + name); Path dir = Paths.get(resolvedModule.reference().location().get()); if (!Files.isDirectory(dir)) throw new RuntimeException("not a directory: " + dir); return dir; }
/** * Test ModuleLayer.defineModulesWithXXX when the modules that override same * named modules in the parent layer. * * Test scenario: * layer1: m1, m2, m3 => same loader * layer2: m1, m2, m4 => same loader */ public void testOverriding1() throws Exception { Configuration cf1 = resolve("m1"); ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null); checkLayer(layer1, "m1", "m2", "m3"); ModuleFinder finder = ModuleFinder.of(MODS_DIR); Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(), Set.of("m1")); ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null); checkLayer(layer2, "m1", "m2", "m3"); invoke(layer1, "m1", "p.Main"); ClassLoader loader1 = layer1.findLoader("m1"); ClassLoader loader2 = layer1.findLoader("m2"); ClassLoader loader3 = layer1.findLoader("m3"); ClassLoader loader4 = layer2.findLoader("m1"); ClassLoader loader5 = layer2.findLoader("m2"); ClassLoader loader6 = layer2.findLoader("m3"); assertTrue(loader1 == loader2); assertTrue(loader1 == loader3); assertTrue(loader4 == loader5); assertTrue(loader4 == loader6); assertTrue(loader4 != loader1); assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1); assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1); assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader4); assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader4); }
/** * Basic test with two modules finders and service binding. * * The before and after ModuleFinders both locate a service provider module * named "m2" that provide implementations of the same service type. */ public void testWithTwoFinders2() { ModuleDescriptor descriptor1 = newBuilder("m1") .exports("p") .uses("p.S") .build(); ModuleDescriptor descriptor2_v1 = newBuilder("m2") .requires("m1") .provides("p.S", List.of("q.T")) .build(); ModuleDescriptor descriptor2_v2 = newBuilder("m2") .requires("m1") .provides("p.S", List.of("q.T")) .build(); ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2_v1); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2_v2); Configuration cf = resolveAndBind(finder1, finder2, "m1"); assertTrue(cf.modules().size() == 2); assertTrue(cf.findModule("m1").isPresent()); assertTrue(cf.findModule("m2").isPresent()); ResolvedModule m1 = cf.findModule("m1").get(); ResolvedModule m2 = cf.findModule("m2").get(); assertEquals(m1.reference().descriptor(), descriptor1); assertEquals(m2.reference().descriptor(), descriptor2_v1); }
/** * Basic test of ModuleLayer.defineModulesWithManyLoaders where one of the * modules is a service provider module. * * Test scenario: * m1 requires m2 and m3 * m1 uses S * m4 provides S with ... */ public void testServicesWithManyLoaders() throws Exception { Configuration cf = resolveAndBind("m1"); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl); checkLayer(layer, "m1", "m2", "m3", "m4"); ClassLoader cl1 = layer.findLoader("m1"); ClassLoader cl2 = layer.findLoader("m2"); ClassLoader cl3 = layer.findLoader("m3"); ClassLoader cl4 = layer.findLoader("m4"); assertTrue(cl1.getParent() == scl); assertTrue(cl2.getParent() == scl); assertTrue(cl3.getParent() == scl); assertTrue(cl4.getParent() == scl); assertTrue(cl2 != cl1); assertTrue(cl3 != cl1); assertTrue(cl3 != cl2); assertTrue(cl4 != cl1); assertTrue(cl4 != cl2); assertTrue(cl4 != cl3); Class<?> serviceType = cl1.loadClass("p.Service"); assertTrue(serviceType.getClassLoader() == cl1); // Test that the service provider can be located via any of // the class loaders in the layer for (Module m : layer.modules()) { ClassLoader loader = m.getClassLoader(); Iterator<?> iter = ServiceLoader.load(serviceType, loader).iterator(); Object provider = iter.next(); assertTrue(serviceType.isInstance(provider)); assertTrue(provider.getClass().getClassLoader() == cl4); assertFalse(iter.hasNext()); } }
/** * 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()); }
/** * Test the empty configuration. */ public void testEmptyConfiguration() { Configuration cf = Configuration.empty(); assertTrue(cf.parents().isEmpty()); assertTrue(cf.modules().isEmpty()); assertFalse(cf.findModule("java.base").isPresent()); }
/** * Basic test of ModuleLayer.defineModulesWithOneLoader where one of the * modules is a service provider module. * * Test scenario: * m1 requires m2 and m3 * m1 uses S * m4 provides S with ... */ public void testServicesWithOneLoader() throws Exception { Configuration cf = resolveAndBind("m1"); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); checkLayer(layer, "m1", "m2", "m3", "m4"); ClassLoader cl1 = layer.findLoader("m1"); ClassLoader cl2 = layer.findLoader("m2"); ClassLoader cl3 = layer.findLoader("m3"); ClassLoader cl4 = layer.findLoader("m4"); assertTrue(cl1.getParent() == scl); assertTrue(cl2 == cl1); assertTrue(cl3 == cl1); assertTrue(cl4 == cl1); Class<?> serviceType = cl1.loadClass("p.Service"); assertTrue(serviceType.getClassLoader() == cl1); Iterator<?> iter = ServiceLoader.load(serviceType, cl1).iterator(); Object provider = iter.next(); assertTrue(serviceType.isInstance(provider)); assertTrue(provider.getClass().getClassLoader() == cl1); assertFalse(iter.hasNext()); }
/** * Returns a Graph containing only requires transitive edges * with transitive reduction. */ public Graph<String> requiresTransitiveGraph(Configuration cf, Set<String> roots) { Deque<String> deque = new ArrayDeque<>(roots); Set<String> visited = new HashSet<>(); Graph.Builder<String> builder = new Graph.Builder<>(); while (deque.peek() != null) { String mn = deque.pop(); if (visited.contains(mn)) continue; visited.add(mn); builder.addNode(mn); cf.findModule(mn).get() .reference().descriptor().requires().stream() .filter(d -> d.modifiers().contains(TRANSITIVE) || d.name().equals("java.base")) .map(Requires::name) .forEach(d -> { deque.add(d); builder.addEdge(mn, d); }); } return builder.build().reduce(); }
/** * Returns Configuration with the given roots */ public Configuration resolve(Set<String> roots) { if (roots.isEmpty()) throw new IllegalArgumentException("empty roots"); return Configuration.empty() .resolve(finder, ModuleFinder.of(), roots); }
public ClassLoader createAndRunFromModule(String moduleName, Path modPath) { ModuleFinder finder = ModuleFinder.of(modPath); ModuleLayer parent = ModuleLayer.boot(); Configuration cf = parent.configuration() .resolve(finder, ModuleFinder.of(), Set.of(moduleName)); ClassLoader scl = ClassLoader.getSystemClassLoader(); ModuleLayer layer = parent.defineModulesWithOneLoader(cf, scl); ClassLoader loader = layer.findLoader(moduleName); ClassLoader ccl = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(loader); return ccl; }
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); } }
/** * Test proxy implementing interfaces in a layer defined in * an unnamed module */ @Test public void testProxyInUnnamed() 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.I", false, loader), Class.forName("p.two.A", false, loader), Class.forName("p.three.P", false, loader), }; Object o = Proxy.newProxyInstance(loader, interfaces, handler); Class<?> proxyClass = o.getClass(); Package pkg = proxyClass.getPackage(); assertFalse(proxyClass.getModule().isNamed()); assertFalse(pkg.isSealed()); assertEquals(proxyClass.getModule().getLayer(), null); }
/** * 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)); }
/** * Returns {@code true} if the configuration contains module mn1 * that reads module mn2. */ static boolean reads(Configuration cf, String mn1, String mn2) { Optional<ResolvedModule> om = cf.findModule(mn1); if (!om.isPresent()) return false; return om.get().reads().stream() .map(ResolvedModule::name) .anyMatch(mn2::equals); }
/** * Test layers with a qualified export. The target module is not in any layer. * * - Configuration/layer1: m1 { } * - Configuration/layer2: m2 { exports p to m3; } */ public void testQualifiedExports7() { // 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 m2 ModuleDescriptor descriptor2 = newBuilder("m2") .exports("p", Set.of("m3")) .build(); ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); Configuration cf2 = resolve(cf1, finder2, "m2"); ClassLoader cl2 = new ClassLoader() { }; ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); assertTrue(layer2.modules().size() == 1); Module m1 = layer1.findModule("m1").get(); Module m2 = layer2.findModule("m2").get(); // check m2 does not export p to anyone assertFalse(m2.isExported("p")); assertFalse(m2.isExported("p", m1)); }
/** * Create a module layer that contains the given system module. */ static Module loadModuleInChildLayer(String mn) { Optional<ModuleReference> omref = ModuleFinder.ofSystem().find(mn); assertTrue("module " + mn + " not a system module", omref.isPresent()); // create a ModuleFinder that only finds this module ModuleReference mref = omref.get(); 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 Collections.singleton(mref); } }; // create a child configuration and layer with this module ModuleLayer bootLayer = ModuleLayer.boot(); Configuration cf = bootLayer .configuration() .resolve(finder, ModuleFinder.of(), Set.of(ANOTHER_MODULE)); ModuleLayer layer = bootLayer.defineModulesWithOneLoader(cf, null); Optional<Module> om = layer.findModule(mn); assertTrue("module " + mn + " not in child layer", om.isPresent()); return om.get(); }