1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @library /test/lib 27 * @modules jdk.compiler 28 * @build LayerAndLoadersTest 29 * jdk.test.lib.compiler.CompilerUtils 30 * jdk.test.lib.util.ModuleUtils 31 * @run testng LayerAndLoadersTest 32 * @summary Tests for java.lang.ModuleLayer@defineModulesWithXXX methods 33 */ 34 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.io.UncheckedIOException; 38 import java.lang.module.Configuration; 39 import java.lang.module.ModuleDescriptor; 40 import java.lang.module.ModuleFinder; 41 import java.lang.module.ModuleReference; 42 import java.lang.module.ResolvedModule; 43 import java.lang.reflect.Method; 44 import java.net.URL; 45 import java.nio.file.Path; 46 import java.nio.file.Paths; 47 import java.util.ArrayList; 48 import java.util.Enumeration; 49 import java.util.HashMap; 50 import java.util.Iterator; 51 import java.util.List; 52 import java.util.Map; 53 import java.util.Optional; 54 import java.util.ServiceLoader; 55 import java.util.Set; 56 import java.util.stream.Collectors; 57 58 import jdk.test.lib.compiler.CompilerUtils; 59 import jdk.test.lib.util.ModuleUtils; 60 61 import org.testng.annotations.BeforeTest; 62 import org.testng.annotations.Test; 63 import static org.testng.Assert.*; 64 65 @Test 66 public class LayerAndLoadersTest { 67 68 private static final String TEST_SRC = System.getProperty("test.src"); 69 70 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 71 private static final Path MODS_DIR = Paths.get("mods"); 72 73 @BeforeTest setup()74 public void setup() throws Exception { 75 // javac -d mods --module-source-path src src/** 76 assertTrue(CompilerUtils.compile(SRC_DIR, MODS_DIR, 77 "--module-source-path", SRC_DIR.toString())); 78 } 79 80 81 /** 82 * Basic test of ModuleLayer.defineModulesWithOneLoader 83 * 84 * Test scenario: 85 * m1 requires m2 and m3 86 */ testWithOneLoader()87 public void testWithOneLoader() throws Exception { 88 Configuration cf = resolve("m1"); 89 90 ClassLoader scl = ClassLoader.getSystemClassLoader(); 91 92 ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); 93 94 checkLayer(layer, "m1", "m2", "m3"); 95 96 ClassLoader cl1 = layer.findLoader("m1"); 97 ClassLoader cl2 = layer.findLoader("m2"); 98 ClassLoader cl3 = layer.findLoader("m3"); 99 100 assertTrue(cl1.getParent() == scl); 101 assertTrue(cl2 == cl1); 102 assertTrue(cl3 == cl1); 103 104 invoke(layer, "m1", "p.Main"); 105 } 106 107 108 /** 109 * Basic test of ModuleLayer.defineModulesWithManyLoaders 110 * 111 * Test scenario: 112 * m1 requires m2 and m3 113 */ testWithManyLoaders()114 public void testWithManyLoaders() throws Exception { 115 Configuration cf = resolve("m1"); 116 117 ClassLoader scl = ClassLoader.getSystemClassLoader(); 118 119 ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl); 120 121 checkLayer(layer, "m1", "m2", "m3"); 122 123 ClassLoader cl1 = layer.findLoader("m1"); 124 ClassLoader cl2 = layer.findLoader("m2"); 125 ClassLoader cl3 = layer.findLoader("m3"); 126 127 assertTrue(cl1.getParent() == scl); 128 assertTrue(cl2.getParent() == scl); 129 assertTrue(cl3.getParent() == scl); 130 assertTrue(cl2 != cl1); 131 assertTrue(cl3 != cl1); 132 assertTrue(cl3 != cl2); 133 134 invoke(layer, "m1", "p.Main"); 135 } 136 137 138 /** 139 * Basic test of ModuleLayer.defineModulesWithOneLoader where one of the 140 * modules is a service provider module. 141 * 142 * Test scenario: 143 * m1 requires m2 and m3 144 * m1 uses S 145 * m4 provides S with ... 146 */ testServicesWithOneLoader()147 public void testServicesWithOneLoader() throws Exception { 148 Configuration cf = resolveAndBind("m1"); 149 150 ClassLoader scl = ClassLoader.getSystemClassLoader(); 151 152 ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); 153 154 checkLayer(layer, "m1", "m2", "m3", "m4"); 155 156 ClassLoader cl1 = layer.findLoader("m1"); 157 ClassLoader cl2 = layer.findLoader("m2"); 158 ClassLoader cl3 = layer.findLoader("m3"); 159 ClassLoader cl4 = layer.findLoader("m4"); 160 161 assertTrue(cl1.getParent() == scl); 162 assertTrue(cl2 == cl1); 163 assertTrue(cl3 == cl1); 164 assertTrue(cl4 == cl1); 165 166 Class<?> serviceType = cl1.loadClass("p.Service"); 167 assertTrue(serviceType.getClassLoader() == cl1); 168 169 Iterator<?> iter = ServiceLoader.load(serviceType, cl1).iterator(); 170 Object provider = iter.next(); 171 assertTrue(serviceType.isInstance(provider)); 172 assertTrue(provider.getClass().getClassLoader() == cl1); 173 assertFalse(iter.hasNext()); 174 } 175 176 177 /** 178 * Basic test of ModuleLayer.defineModulesWithManyLoaders where one of the 179 * modules is a service provider module. 180 * 181 * Test scenario: 182 * m1 requires m2 and m3 183 * m1 uses S 184 * m4 provides S with ... 185 */ testServicesWithManyLoaders()186 public void testServicesWithManyLoaders() throws Exception { 187 Configuration cf = resolveAndBind("m1"); 188 189 ClassLoader scl = ClassLoader.getSystemClassLoader(); 190 191 ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl); 192 193 checkLayer(layer, "m1", "m2", "m3", "m4"); 194 195 ClassLoader cl1 = layer.findLoader("m1"); 196 ClassLoader cl2 = layer.findLoader("m2"); 197 ClassLoader cl3 = layer.findLoader("m3"); 198 ClassLoader cl4 = layer.findLoader("m4"); 199 200 assertTrue(cl1.getParent() == scl); 201 assertTrue(cl2.getParent() == scl); 202 assertTrue(cl3.getParent() == scl); 203 assertTrue(cl4.getParent() == scl); 204 assertTrue(cl2 != cl1); 205 assertTrue(cl3 != cl1); 206 assertTrue(cl3 != cl2); 207 assertTrue(cl4 != cl1); 208 assertTrue(cl4 != cl2); 209 assertTrue(cl4 != cl3); 210 211 Class<?> serviceType = cl1.loadClass("p.Service"); 212 assertTrue(serviceType.getClassLoader() == cl1); 213 214 // Test that the service provider can be located via any of 215 // the class loaders in the layer 216 for (Module m : layer.modules()) { 217 ClassLoader loader = m.getClassLoader(); 218 Iterator<?> iter = ServiceLoader.load(serviceType, loader).iterator(); 219 Object provider = iter.next(); 220 assertTrue(serviceType.isInstance(provider)); 221 assertTrue(provider.getClass().getClassLoader() == cl4); 222 assertFalse(iter.hasNext()); 223 } 224 } 225 226 227 /** 228 * Tests that the class loaders created by defineModulesWithXXX delegate 229 * to the given parent class loader. 230 */ testDelegationToParent()231 public void testDelegationToParent() throws Exception { 232 Configuration cf = resolve("m1"); 233 234 ClassLoader parent = this.getClass().getClassLoader(); 235 String cn = this.getClass().getName(); 236 237 // one loader 238 ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, parent); 239 testLoad(layer, cn); 240 241 // one loader with boot loader as parent 242 layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, null); 243 testLoadFail(layer, cn); 244 245 // many loaders 246 layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, parent); 247 testLoad(layer, cn); 248 249 // many loader with boot loader as parent 250 layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null); 251 testLoadFail(layer, cn); 252 } 253 254 255 /** 256 * Test defineModulesWithXXX when modules that have overlapping packages. 257 * 258 * Test scenario: 259 * m1 exports p 260 * m2 exports p 261 */ testOverlappingPackages()262 public void testOverlappingPackages() { 263 ModuleDescriptor descriptor1 264 = ModuleDescriptor.newModule("m1").exports("p").build(); 265 266 ModuleDescriptor descriptor2 267 = ModuleDescriptor.newModule("m2").exports("p").build(); 268 269 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 270 271 Configuration cf = ModuleLayer.boot() 272 .configuration() 273 .resolve(finder, ModuleFinder.of(), Set.of("m1", "m2")); 274 275 // cannot define both module m1 and m2 to the same class loader 276 try { 277 ModuleLayer.boot().defineModulesWithOneLoader(cf, null); 278 assertTrue(false); 279 } catch (LayerInstantiationException expected) { } 280 281 // should be okay to have one module per class loader 282 ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null); 283 checkLayer(layer, "m1", "m2"); 284 } 285 286 287 /** 288 * Test ModuleLayer.defineModulesWithXXX with split delegation. 289 * 290 * Test scenario: 291 * layer1: m1 exports p, m2 exports p 292 * layer2: m3 reads m1, m4 reads m2 293 */ testSplitDelegation()294 public void testSplitDelegation() { 295 ModuleDescriptor descriptor1 296 = ModuleDescriptor.newModule("m1").exports("p").build(); 297 298 ModuleDescriptor descriptor2 299 = ModuleDescriptor.newModule("m2").exports("p").build(); 300 301 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 302 303 Configuration cf1 = ModuleLayer.boot() 304 .configuration() 305 .resolve(finder1, ModuleFinder.of(), Set.of("m1", "m2")); 306 307 ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null); 308 checkLayer(layer1, "m1", "m2"); 309 310 ModuleDescriptor descriptor3 311 = ModuleDescriptor.newModule("m3").requires("m1").build(); 312 313 ModuleDescriptor descriptor4 314 = ModuleDescriptor.newModule("m4").requires("m2").build(); 315 316 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); 317 318 Configuration cf2 = cf1.resolve(finder2, ModuleFinder.of(), 319 Set.of("m3", "m4")); 320 321 // package p cannot be supplied by two class loaders 322 try { 323 layer1.defineModulesWithOneLoader(cf2, null); 324 assertTrue(false); 325 } catch (LayerInstantiationException expected) { } 326 327 // no split delegation when modules have their own class loader 328 ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); 329 checkLayer(layer2, "m3", "m4"); 330 } 331 332 333 /** 334 * Test ModuleLayer.defineModulesWithXXX when the modules that override same 335 * named modules in the parent layer. 336 * 337 * Test scenario: 338 * layer1: m1, m2, m3 => same loader 339 * layer2: m1, m2, m4 => same loader 340 */ testOverriding1()341 public void testOverriding1() throws Exception { 342 Configuration cf1 = resolve("m1"); 343 344 ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null); 345 checkLayer(layer1, "m1", "m2", "m3"); 346 347 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 348 Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(), 349 Set.of("m1")); 350 351 ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null); 352 checkLayer(layer2, "m1", "m2", "m3"); 353 invoke(layer1, "m1", "p.Main"); 354 355 ClassLoader loader1 = layer1.findLoader("m1"); 356 ClassLoader loader2 = layer1.findLoader("m2"); 357 ClassLoader loader3 = layer1.findLoader("m3"); 358 359 ClassLoader loader4 = layer2.findLoader("m1"); 360 ClassLoader loader5 = layer2.findLoader("m2"); 361 ClassLoader loader6 = layer2.findLoader("m3"); 362 363 assertTrue(loader1 == loader2); 364 assertTrue(loader1 == loader3); 365 366 assertTrue(loader4 == loader5); 367 assertTrue(loader4 == loader6); 368 assertTrue(loader4 != loader1); 369 370 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 371 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1); 372 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1); 373 374 assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); 375 assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader4); 376 assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader4); 377 } 378 379 380 /** 381 * Test Layer defineModulesWithXXX when the modules that override same 382 * named modules in the parent layer. 383 * 384 * Test scenario: 385 * layer1: m1, m2, m3 => loader pool 386 * layer2: m1, m2, m3 => loader pool 387 */ testOverriding2()388 public void testOverriding2() throws Exception { 389 Configuration cf1 = resolve("m1"); 390 391 ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null); 392 checkLayer(layer1, "m1", "m2", "m3"); 393 394 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 395 Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(), 396 Set.of("m1")); 397 398 ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); 399 checkLayer(layer2, "m1", "m2", "m3"); 400 invoke(layer1, "m1", "p.Main"); 401 402 ClassLoader loader1 = layer1.findLoader("m1"); 403 ClassLoader loader2 = layer1.findLoader("m2"); 404 ClassLoader loader3 = layer1.findLoader("m3"); 405 406 ClassLoader loader4 = layer2.findLoader("m1"); 407 ClassLoader loader5 = layer2.findLoader("m2"); 408 ClassLoader loader6 = layer2.findLoader("m3"); 409 410 assertTrue(loader4 != loader1); 411 assertTrue(loader5 != loader2); 412 assertTrue(loader6 != loader3); 413 414 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 415 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2); 416 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3); 417 418 // p.Main is not visible via loader2 419 try { 420 loader2.loadClass("p.Main"); 421 assertTrue(false); 422 } catch (ClassNotFoundException expected) { } 423 424 // w.Hello is not visible via loader2 425 try { 426 loader2.loadClass("w.Hello"); 427 assertTrue(false); 428 } catch (ClassNotFoundException expected) { } 429 430 // p.Main is not visible via loader3 431 try { 432 loader3.loadClass("p.Main"); 433 assertTrue(false); 434 } catch (ClassNotFoundException expected) { } 435 436 // q.Hello is not visible via loader3 437 try { 438 loader3.loadClass("q.Hello"); 439 assertTrue(false); 440 } catch (ClassNotFoundException expected) { } 441 442 443 assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); 444 assertTrue(loader5.loadClass("q.Hello").getClassLoader() == loader5); 445 assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6); 446 447 // p.Main is not visible via loader5 448 try { 449 loader5.loadClass("p.Main"); 450 assertTrue(false); 451 } catch (ClassNotFoundException expected) { } 452 453 // w.Hello is not visible via loader5 454 try { 455 loader5.loadClass("w.Hello"); 456 assertTrue(false); 457 } catch (ClassNotFoundException expected) { } 458 459 // p.Main is not visible via loader6 460 try { 461 loader6.loadClass("p.Main"); 462 assertTrue(false); 463 } catch (ClassNotFoundException expected) { } 464 465 // q.Hello is not visible via loader6 466 try { 467 loader6.loadClass("q.Hello"); 468 assertTrue(false); 469 } catch (ClassNotFoundException expected) { } 470 } 471 472 473 /** 474 * Test ModuleLayer.defineModulesWithXXX when the modules that override same 475 * named modules in the parent layer. 476 * 477 * layer1: m1, m2, m3 => same loader 478 * layer2: m1, m3 => same loader 479 */ testOverriding3()480 public void testOverriding3() throws Exception { 481 Configuration cf1 = resolve("m1"); 482 483 ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null); 484 checkLayer(layer1, "m1", "m2", "m3"); 485 486 ModuleFinder finder = finderFor("m1", "m3"); 487 488 Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(), 489 Set.of("m1")); 490 491 ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null); 492 checkLayer(layer2, "m1", "m3"); 493 invoke(layer1, "m1", "p.Main"); 494 495 ClassLoader loader1 = layer1.findLoader("m1"); 496 ClassLoader loader2 = layer2.findLoader("m1"); 497 498 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 499 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1); 500 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1); 501 502 assertTrue(loader2.loadClass("p.Main").getClassLoader() == loader2); 503 assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader1); 504 assertTrue(loader2.loadClass("w.Hello").getClassLoader() == loader2); 505 } 506 507 508 /** 509 * Test Layer defineModulesWithXXX when the modules that override same 510 * named modules in the parent layer. 511 * 512 * layer1: m1, m2, m3 => loader pool 513 * layer2: m1, m3 => loader pool 514 */ testOverriding4()515 public void testOverriding4() throws Exception { 516 Configuration cf1 = resolve("m1"); 517 518 ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null); 519 checkLayer(layer1, "m1", "m2", "m3"); 520 521 ModuleFinder finder = finderFor("m1", "m3"); 522 523 Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(), 524 Set.of("m1")); 525 526 ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); 527 checkLayer(layer2, "m1", "m3"); 528 invoke(layer1, "m1", "p.Main"); 529 530 ClassLoader loader1 = layer1.findLoader("m1"); 531 ClassLoader loader2 = layer1.findLoader("m2"); 532 ClassLoader loader3 = layer1.findLoader("m3"); 533 534 ClassLoader loader4 = layer2.findLoader("m1"); 535 ClassLoader loader5 = layer2.findLoader("m2"); 536 ClassLoader loader6 = layer2.findLoader("m3"); 537 538 assertTrue(loader4 != loader1); 539 assertTrue(loader5 == loader2); // m2 not overridden 540 assertTrue(loader6 != loader3); 541 542 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 543 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2); 544 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3); 545 546 assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader2); 547 548 assertTrue(loader3.loadClass("w.Hello").getClassLoader() == loader3); 549 550 assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); 551 assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader2); 552 assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader6); 553 554 assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6); 555 } 556 557 /** 558 * Basic test for locating resources with a class loader created by 559 * defineModulesWithOneLoader. 560 */ testResourcesWithOneLoader()561 public void testResourcesWithOneLoader() throws Exception { 562 testResourcesWithOneLoader(ClassLoader.getSystemClassLoader()); 563 testResourcesWithOneLoader(null); 564 } 565 566 /** 567 * Test locating resources with the class loader created by 568 * defineModulesWithOneLoader. The class loader has the given class 569 * loader as its parent. 570 */ testResourcesWithOneLoader(ClassLoader parent)571 void testResourcesWithOneLoader(ClassLoader parent) throws Exception { 572 Configuration cf = resolve("m1"); 573 ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, parent); 574 575 ClassLoader loader = layer.findLoader("m1"); 576 assertNotNull(loader); 577 assertTrue(loader.getParent() == parent); 578 579 // check that getResource and getResources are consistent 580 URL url1 = loader.getResource("module-info.class"); 581 URL url2 = loader.getResources("module-info.class").nextElement(); 582 assertEquals(url1.toURI(), url2.toURI()); 583 584 // use getResources to find module-info.class resources 585 Enumeration<URL> urls = loader.getResources("module-info.class"); 586 List<String> list = readModuleNames(urls); 587 588 // m1, m2, ... should be first (order not specified) 589 int count = cf.modules().size(); 590 cf.modules().stream() 591 .map(ResolvedModule::name) 592 .forEach(mn -> assertTrue(list.indexOf(mn) < count)); 593 594 // java.base should be after m1, m2, ... 595 assertTrue(list.indexOf("java.base") >= count); 596 597 // check resources(String) 598 List<String> list2 = loader.resources("module-info.class") 599 .map(this::readModuleName) 600 .collect(Collectors.toList()); 601 assertEquals(list2, list); 602 603 // check nulls 604 try { 605 loader.getResource(null); 606 assertTrue(false); 607 } catch (NullPointerException e) { } 608 try { 609 loader.getResources(null); 610 assertTrue(false); 611 } catch (NullPointerException e) { } 612 try { 613 loader.resources(null); 614 assertTrue(false); 615 } catch (NullPointerException e) { } 616 } 617 618 /** 619 * Basic test for locating resources with class loaders created by 620 * defineModulesWithManyLoaders. 621 */ testResourcesWithManyLoaders()622 public void testResourcesWithManyLoaders() throws Exception { 623 testResourcesWithManyLoaders(ClassLoader.getSystemClassLoader()); 624 testResourcesWithManyLoaders(null); 625 } 626 627 /** 628 * Test locating resources with class loaders created by 629 * defineModulesWithManyLoaders. The class loaders have the given class 630 * loader as their parent. 631 */ testResourcesWithManyLoaders(ClassLoader parent)632 void testResourcesWithManyLoaders(ClassLoader parent) throws Exception { 633 Configuration cf = resolve("m1"); 634 ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, parent); 635 636 for (Module m : layer.modules()) { 637 String name = m.getName(); 638 ClassLoader loader = m.getClassLoader(); 639 assertNotNull(loader); 640 assertTrue(loader.getParent() == parent); 641 642 // getResource should find the module-info.class for the module 643 URL url = loader.getResource("module-info.class"); 644 assertEquals(readModuleName(url), name); 645 646 // list of modules names read from module-info.class 647 Enumeration<URL> urls = loader.getResources("module-info.class"); 648 List<String> list = readModuleNames(urls); 649 650 // module should be the first element 651 assertTrue(list.indexOf(name) == 0); 652 653 // the module-info.class for the other modules in the layer 654 // should not be found 655 layer.modules().stream() 656 .map(Module::getName) 657 .filter(mn -> !mn.equals(name)) 658 .forEach(mn -> assertTrue(list.indexOf(mn) < 0)); 659 660 // java.base cannot be the first element 661 assertTrue(list.indexOf("java.base") > 0); 662 663 // check resources(String) 664 List<String> list2 = loader.resources("module-info.class") 665 .map(this::readModuleName) 666 .collect(Collectors.toList()); 667 assertEquals(list2, list); 668 669 // check nulls 670 try { 671 loader.getResource(null); 672 assertTrue(false); 673 } catch (NullPointerException e) { } 674 try { 675 loader.getResources(null); 676 assertTrue(false); 677 } catch (NullPointerException e) { } 678 try { 679 loader.resources(null); 680 assertTrue(false); 681 } catch (NullPointerException e) { } 682 } 683 } 684 readModuleNames(Enumeration<URL> e)685 private List<String> readModuleNames(Enumeration<URL> e) { 686 List<String> list = new ArrayList<>(); 687 while (e.hasMoreElements()) { 688 URL url = e.nextElement(); 689 list.add(readModuleName(url)); 690 } 691 return list; 692 } 693 readModuleName(URL url)694 private String readModuleName(URL url) { 695 try (InputStream in = url.openStream()) { 696 ModuleDescriptor descriptor = ModuleDescriptor.read(in); 697 return descriptor.name(); 698 } catch (IOException ioe) { 699 throw new UncheckedIOException(ioe); 700 } 701 } 702 703 704 // -- supporting methods -- 705 706 707 /** 708 * Resolve the given modules, by name, and returns the resulting 709 * Configuration. 710 */ resolve(String... roots)711 private static Configuration resolve(String... roots) { 712 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 713 return ModuleLayer.boot() 714 .configuration() 715 .resolve(finder, ModuleFinder.of(), Set.of(roots)); 716 } 717 718 /** 719 * Resolve the given modules, by name, and returns the resulting 720 * Configuration. 721 */ resolveAndBind(String... roots)722 private static Configuration resolveAndBind(String... roots) { 723 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 724 return ModuleLayer.boot() 725 .configuration() 726 .resolveAndBind(finder, ModuleFinder.of(), Set.of(roots)); 727 } 728 729 730 /** 731 * Invokes the static void main(String[]) method on the given class 732 * in the given module. 733 */ invoke(ModuleLayer layer, String mn, String mc)734 private static void invoke(ModuleLayer layer, String mn, String mc) throws Exception { 735 ClassLoader loader = layer.findLoader(mn); 736 Class<?> c = loader.loadClass(mc); 737 Method mainMethod = c.getMethod("main", String[].class); 738 mainMethod.invoke(null, (Object)new String[0]); 739 } 740 741 742 /** 743 * Checks that the given layer contains exactly the expected modules 744 * (by name). 745 */ checkLayer(ModuleLayer layer, String ... expected)746 private void checkLayer(ModuleLayer layer, String ... expected) { 747 Set<String> names = layer.modules().stream() 748 .map(Module::getName) 749 .collect(Collectors.toSet()); 750 assertTrue(names.size() == expected.length); 751 for (String name : expected) { 752 assertTrue(names.contains(name)); 753 } 754 } 755 756 757 /** 758 * Test that a class can be loaded via the class loader of all modules 759 * in the given layer. 760 */ testLoad(ModuleLayer layer, String cn)761 static void testLoad(ModuleLayer layer, String cn) throws Exception { 762 for (Module m : layer.modules()) { 763 ClassLoader l = m.getClassLoader(); 764 l.loadClass(cn); 765 } 766 } 767 768 769 /** 770 * Test that a class cannot be loaded via any of the class loaders of 771 * the modules in the given layer. 772 */ testLoadFail(ModuleLayer layer, String cn)773 static void testLoadFail(ModuleLayer layer, String cn) throws Exception { 774 for (Module m : layer.modules()) { 775 ClassLoader l = m.getClassLoader(); 776 try { 777 l.loadClass(cn); 778 assertTrue(false); 779 } catch (ClassNotFoundException expected) { } 780 } 781 } 782 783 784 /** 785 * Returns a ModuleFinder that only finds the given test modules 786 */ finderFor(String... names)787 static ModuleFinder finderFor(String... names) { 788 789 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 790 791 Map<String, ModuleReference> mrefs = new HashMap<>(); 792 for (String name : names) { 793 Optional<ModuleReference> omref = finder.find(name); 794 assert omref.isPresent(); 795 mrefs.put(name, omref.get()); 796 } 797 798 return new ModuleFinder() { 799 @Override 800 public Optional<ModuleReference> find(String name) { 801 ModuleReference mref = mrefs.get(name); 802 return Optional.ofNullable(mref); 803 } 804 @Override 805 public Set<ModuleReference> findAll() { 806 return mrefs.values().stream().collect(Collectors.toSet()); 807 } 808 }; 809 } 810 811 } 812