1 /* 2 * Copyright (c) 2015, 2016, 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 /lib/testlibrary 27 * @modules jdk.compiler 28 * @build LayerAndLoadersTest CompilerUtils ModuleUtils 29 * @run testng LayerAndLoadersTest 30 * @summary Tests for java.lang.reflect.Layer@createWithXXX methods 31 */ 32 33 import java.lang.module.Configuration; 34 import java.lang.module.ModuleDescriptor; 35 import java.lang.module.ModuleFinder; 36 import java.lang.module.ModuleReference; 37 import java.lang.reflect.Layer; 38 import java.lang.reflect.LayerInstantiationException; 39 import java.lang.reflect.Method; 40 import java.lang.reflect.Module; 41 import java.nio.file.Path; 42 import java.nio.file.Paths; 43 import java.util.HashMap; 44 import java.util.Iterator; 45 import java.util.Map; 46 import java.util.Optional; 47 import java.util.ServiceLoader; 48 import java.util.Set; 49 import java.util.stream.Collectors; 50 51 import org.testng.annotations.BeforeTest; 52 import org.testng.annotations.Test; 53 import static org.testng.Assert.*; 54 55 @Test 56 public class LayerAndLoadersTest { 57 58 private static final String TEST_SRC = System.getProperty("test.src"); 59 60 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 61 private static final Path MODS_DIR = Paths.get("mods"); 62 63 @BeforeTest 64 public void setup() throws Exception { 65 66 // javac -d mods --module-source-path src src/** 67 assertTrue(CompilerUtils.compile(SRC_DIR, MODS_DIR, 68 "--module-source-path", SRC_DIR.toString())); 69 } 70 71 72 /** 73 * Basic test of Layer defineModulesWithOneLoader 74 * 75 * Test scenario: 76 * m1 requires m2 and m3 77 */ 78 public void testWithOneLoader() throws Exception { 79 80 Configuration cf = resolveRequires("m1"); 81 82 ClassLoader scl = ClassLoader.getSystemClassLoader(); 83 84 Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl); 85 86 checkLayer(layer, "m1", "m2", "m3"); 87 88 ClassLoader cl1 = layer.findLoader("m1"); 89 ClassLoader cl2 = layer.findLoader("m2"); 90 ClassLoader cl3 = layer.findLoader("m3"); 91 92 assertTrue(cl1.getParent() == scl); 93 assertTrue(cl2 == cl1); 94 assertTrue(cl3 == cl1); 95 96 invoke(layer, "m1", "p.Main"); 97 98 } 99 100 101 /** 102 * Basic test of Layer defineModulesWithManyLoaders 103 * 104 * Test scenario: 105 * m1 requires m2 and m3 106 */ 107 public void testWithManyLoaders() throws Exception { 108 109 Configuration cf = resolveRequires("m1"); 110 111 ClassLoader scl = ClassLoader.getSystemClassLoader(); 112 113 Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl); 114 115 checkLayer(layer, "m1", "m2", "m3"); 116 117 ClassLoader cl1 = layer.findLoader("m1"); 118 ClassLoader cl2 = layer.findLoader("m2"); 119 ClassLoader cl3 = layer.findLoader("m3"); 120 121 assertTrue(cl1.getParent() == scl); 122 assertTrue(cl2.getParent() == scl); 123 assertTrue(cl3.getParent() == scl); 124 assertTrue(cl2 != cl1); 125 assertTrue(cl3 != cl1); 126 assertTrue(cl3 != cl2); 127 128 invoke(layer, "m1", "p.Main"); 129 130 } 131 132 133 /** 134 * Basic test of Layer defineModulesWithOneLoader where one of the modules 135 * is a service provider module. 136 * 137 * Test scenario: 138 * m1 requires m2 and m3 139 * m1 uses S 140 * m4 provides S with ... 141 */ 142 public void testServicesWithOneLoader() throws Exception { 143 144 Configuration cf = resolveRequiresAndUses("m1"); 145 146 ClassLoader scl = ClassLoader.getSystemClassLoader(); 147 148 Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl); 149 150 checkLayer(layer, "m1", "m2", "m3", "m4"); 151 152 ClassLoader cl1 = layer.findLoader("m1"); 153 ClassLoader cl2 = layer.findLoader("m2"); 154 ClassLoader cl3 = layer.findLoader("m3"); 155 ClassLoader cl4 = layer.findLoader("m4"); 156 157 assertTrue(cl1.getParent() == scl); 158 assertTrue(cl2 == cl1); 159 assertTrue(cl3 == cl1); 160 assertTrue(cl4 == cl1); 161 162 Class<?> serviceType = cl1.loadClass("p.Service"); 163 assertTrue(serviceType.getClassLoader() == cl1); 164 165 Iterator<?> iter = ServiceLoader.load(serviceType, cl1).iterator(); 166 Object provider = iter.next(); 167 assertTrue(serviceType.isInstance(provider)); 168 assertTrue(provider.getClass().getClassLoader() == cl1); 169 assertFalse(iter.hasNext()); 170 171 } 172 173 174 /** 175 * Basic test of Layer defineModulesWithManyLoaders where one of the 176 * modules is a service provider module. 177 * 178 * Test scenario: 179 * m1 requires m2 and m3 180 * m1 uses S 181 * m4 provides S with ... 182 */ 183 public void testServicesWithManyLoaders() throws Exception { 184 185 Configuration cf = resolveRequiresAndUses("m1"); 186 187 ClassLoader scl = ClassLoader.getSystemClassLoader(); 188 189 Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, scl); 190 191 checkLayer(layer, "m1", "m2", "m3", "m4"); 192 193 ClassLoader cl1 = layer.findLoader("m1"); 194 ClassLoader cl2 = layer.findLoader("m2"); 195 ClassLoader cl3 = layer.findLoader("m3"); 196 ClassLoader cl4 = layer.findLoader("m4"); 197 198 assertTrue(cl1.getParent() == scl); 199 assertTrue(cl2.getParent() == scl); 200 assertTrue(cl3.getParent() == scl); 201 assertTrue(cl4.getParent() == scl); 202 assertTrue(cl2 != cl1); 203 assertTrue(cl3 != cl1); 204 assertTrue(cl3 != cl2); 205 assertTrue(cl4 != cl1); 206 assertTrue(cl4 != cl2); 207 assertTrue(cl4 != cl3); 208 209 Class<?> serviceType = cl1.loadClass("p.Service"); 210 assertTrue(serviceType.getClassLoader() == cl1); 211 212 // Test that the service provider can be located via any of 213 // the class loaders in the layer 214 for (Module m : layer.modules()) { 215 ClassLoader loader = m.getClassLoader(); 216 Iterator<?> iter = ServiceLoader.load(serviceType, loader).iterator(); 217 Object provider = iter.next(); 218 assertTrue(serviceType.isInstance(provider)); 219 assertTrue(provider.getClass().getClassLoader() == cl4); 220 assertFalse(iter.hasNext()); 221 } 222 223 } 224 225 226 /** 227 * Tests that the class loaders created by defineModulesWithXXX delegate 228 * to the given parent class loader. 229 */ 230 public void testDelegationToParent() throws Exception { 231 232 Configuration cf = resolveRequires("m1"); 233 234 ClassLoader parent = this.getClass().getClassLoader(); 235 String cn = this.getClass().getName(); 236 237 // one loader 238 Layer layer = Layer.boot().defineModulesWithOneLoader(cf, parent); 239 testLoad(layer, cn); 240 241 // one loader with boot loader as parent 242 layer = Layer.boot().defineModulesWithOneLoader(cf, null); 243 testLoadFail(layer, cn); 244 245 // many loaders 246 layer = Layer.boot().defineModulesWithManyLoaders(cf, parent); 247 testLoad(layer, cn); 248 249 // many loader with boot loader as parent 250 layer = Layer.boot().defineModulesWithManyLoaders(cf, null); 251 testLoadFail(layer, cn); 252 253 } 254 255 256 /** 257 * Test defineModulesWithXXX when modules that have overlapping packages. 258 * 259 * Test scenario: 260 * m1 exports p 261 * m2 exports p 262 */ 263 public void testOverlappingPackages() { 264 265 ModuleDescriptor descriptor1 266 = new ModuleDescriptor.Builder("m1").exports("p").build(); 267 268 ModuleDescriptor descriptor2 269 = new ModuleDescriptor.Builder("m2").exports("p").build(); 270 271 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 272 273 Configuration cf = Layer.boot() 274 .configuration() 275 .resolveRequires(finder, ModuleFinder.of(), Set.of("m1", "m2")); 276 277 // cannot define both module m1 and m2 to the same class loader 278 try { 279 Layer.boot().defineModulesWithOneLoader(cf, null); 280 assertTrue(false); 281 } catch (LayerInstantiationException expected) { } 282 283 // should be okay to have one module per class loader 284 Layer layer = Layer.boot().defineModulesWithManyLoaders(cf, null); 285 checkLayer(layer, "m1", "m2"); 286 287 } 288 289 290 /** 291 * Test Layer defineModulesWithXXX with split delegation. 292 * 293 * Test scenario: 294 * layer1: m1 exports p, m2 exports p 295 * layer2: m3 reads m1, m4 reads m2 296 */ 297 public void testSplitDelegation() { 298 299 ModuleDescriptor descriptor1 300 = new ModuleDescriptor.Builder("m1").exports("p").build(); 301 302 ModuleDescriptor descriptor2 303 = new ModuleDescriptor.Builder("m2").exports("p").build(); 304 305 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 306 307 Configuration cf1 = Layer.boot() 308 .configuration() 309 .resolveRequires(finder1, ModuleFinder.of(), Set.of("m1", "m2")); 310 311 Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null); 312 checkLayer(layer1, "m1", "m2"); 313 314 ModuleDescriptor descriptor3 315 = new ModuleDescriptor.Builder("m3").requires("m1").build(); 316 317 ModuleDescriptor descriptor4 318 = new ModuleDescriptor.Builder("m4").requires("m2").build(); 319 320 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); 321 322 Configuration cf2 = cf1.resolveRequires(finder2, ModuleFinder.of(), 323 Set.of("m3", "m4")); 324 325 // package p cannot be supplied by two class loaders 326 try { 327 layer1.defineModulesWithOneLoader(cf2, null); 328 assertTrue(false); 329 } catch (LayerInstantiationException expected) { } 330 331 // no split delegation when modules have their own class loader 332 Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); 333 checkLayer(layer2, "m3", "m4"); 334 335 } 336 337 338 /** 339 * Test Layer defineModulesWithXXX when the modules that override same 340 * named modules in the parent layer. 341 * 342 * Test scenario: 343 * layer1: m1, m2, m3 => same loader 344 * layer2: m1, m2, m4 => same loader 345 */ 346 public void testOverriding1() throws Exception { 347 348 Configuration cf1 = resolveRequires("m1"); 349 350 Layer layer1 = Layer.boot().defineModulesWithOneLoader(cf1, null); 351 checkLayer(layer1, "m1", "m2", "m3"); 352 353 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 354 Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), 355 Set.of("m1")); 356 357 Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null); 358 checkLayer(layer2, "m1", "m2", "m3"); 359 invoke(layer1, "m1", "p.Main"); 360 361 ClassLoader loader1 = layer1.findLoader("m1"); 362 ClassLoader loader2 = layer1.findLoader("m2"); 363 ClassLoader loader3 = layer1.findLoader("m3"); 364 365 ClassLoader loader4 = layer2.findLoader("m1"); 366 ClassLoader loader5 = layer2.findLoader("m2"); 367 ClassLoader loader6 = layer2.findLoader("m3"); 368 369 assertTrue(loader1 == loader2); 370 assertTrue(loader1 == loader3); 371 372 assertTrue(loader4 == loader5); 373 assertTrue(loader4 == loader6); 374 assertTrue(loader4 != loader1); 375 376 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 377 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1); 378 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1); 379 380 assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); 381 assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader4); 382 assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader4); 383 384 } 385 386 387 /** 388 * Test Layer defineModulesWithXXX when the modules that override same 389 * named modules in the parent layer. 390 * 391 * Test scenario: 392 * layer1: m1, m2, m3 => loader pool 393 * layer2: m1, m2, m3 => loader pool 394 */ 395 public void testOverriding2() throws Exception { 396 397 Configuration cf1 = resolveRequires("m1"); 398 399 Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null); 400 checkLayer(layer1, "m1", "m2", "m3"); 401 402 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 403 Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), 404 Set.of("m1")); 405 406 Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); 407 checkLayer(layer2, "m1", "m2", "m3"); 408 invoke(layer1, "m1", "p.Main"); 409 410 ClassLoader loader1 = layer1.findLoader("m1"); 411 ClassLoader loader2 = layer1.findLoader("m2"); 412 ClassLoader loader3 = layer1.findLoader("m3"); 413 414 ClassLoader loader4 = layer2.findLoader("m1"); 415 ClassLoader loader5 = layer2.findLoader("m2"); 416 ClassLoader loader6 = layer2.findLoader("m3"); 417 418 assertTrue(loader4 != loader1); 419 assertTrue(loader5 != loader2); 420 assertTrue(loader6 != loader3); 421 422 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 423 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2); 424 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3); 425 426 // p.Main is not visible via loader2 427 try { 428 loader2.loadClass("p.Main"); 429 assertTrue(false); 430 } catch (ClassNotFoundException expected) { } 431 432 // w.Hello is not visible via loader2 433 try { 434 loader2.loadClass("w.Hello"); 435 assertTrue(false); 436 } catch (ClassNotFoundException expected) { } 437 438 // p.Main is not visible via loader3 439 try { 440 loader3.loadClass("p.Main"); 441 assertTrue(false); 442 } catch (ClassNotFoundException expected) { } 443 444 // q.Hello is not visible via loader3 445 try { 446 loader3.loadClass("q.Hello"); 447 assertTrue(false); 448 } catch (ClassNotFoundException expected) { } 449 450 451 assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); 452 assertTrue(loader5.loadClass("q.Hello").getClassLoader() == loader5); 453 assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6); 454 455 // p.Main is not visible via loader5 456 try { 457 loader5.loadClass("p.Main"); 458 assertTrue(false); 459 } catch (ClassNotFoundException expected) { } 460 461 // w.Hello is not visible via loader5 462 try { 463 loader5.loadClass("w.Hello"); 464 assertTrue(false); 465 } catch (ClassNotFoundException expected) { } 466 467 // p.Main is not visible via loader6 468 try { 469 loader6.loadClass("p.Main"); 470 assertTrue(false); 471 } catch (ClassNotFoundException expected) { } 472 473 // q.Hello is not visible via loader6 474 try { 475 loader6.loadClass("q.Hello"); 476 assertTrue(false); 477 } catch (ClassNotFoundException expected) { } 478 479 } 480 481 482 /** 483 * Test Layer defineModulesWithXXX when the modules that override same 484 * named modules in the parent layer. 485 * 486 * layer1: m1, m2, m3 => same loader 487 * layer2: m1, m3 => same loader 488 */ 489 public void testOverriding3() throws Exception { 490 491 Configuration cf1 = resolveRequires("m1"); 492 493 Layer layer1 = Layer.boot().defineModulesWithOneLoader(cf1, null); 494 checkLayer(layer1, "m1", "m2", "m3"); 495 496 ModuleFinder finder = finderFor("m1", "m3"); 497 498 Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), 499 Set.of("m1")); 500 501 Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null); 502 checkLayer(layer2, "m1", "m3"); 503 invoke(layer1, "m1", "p.Main"); 504 505 ClassLoader loader1 = layer1.findLoader("m1"); 506 ClassLoader loader2 = layer2.findLoader("m1"); 507 508 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 509 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1); 510 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1); 511 512 assertTrue(loader2.loadClass("p.Main").getClassLoader() == loader2); 513 assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader1); 514 assertTrue(loader2.loadClass("w.Hello").getClassLoader() == loader2); 515 516 } 517 518 519 /** 520 * Test Layer defineModulesWithXXX when the modules that override same 521 * named modules in the parent layer. 522 * 523 * layer1: m1, m2, m3 => loader pool 524 * layer2: m1, m3 => loader pool 525 */ 526 public void testOverriding4() throws Exception { 527 528 Configuration cf1 = resolveRequires("m1"); 529 530 Layer layer1 = Layer.boot().defineModulesWithManyLoaders(cf1, null); 531 checkLayer(layer1, "m1", "m2", "m3"); 532 533 ModuleFinder finder = finderFor("m1", "m3"); 534 535 Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), 536 Set.of("m1")); 537 538 Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); 539 checkLayer(layer2, "m1", "m3"); 540 invoke(layer1, "m1", "p.Main"); 541 542 ClassLoader loader1 = layer1.findLoader("m1"); 543 ClassLoader loader2 = layer1.findLoader("m2"); 544 ClassLoader loader3 = layer1.findLoader("m3"); 545 546 ClassLoader loader4 = layer2.findLoader("m1"); 547 ClassLoader loader5 = layer2.findLoader("m2"); 548 ClassLoader loader6 = layer2.findLoader("m3"); 549 550 assertTrue(loader4 != loader1); 551 assertTrue(loader5 == loader2); // m2 not overridden 552 assertTrue(loader6 != loader3); 553 554 assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1); 555 assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2); 556 assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3); 557 558 assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader2); 559 560 assertTrue(loader3.loadClass("w.Hello").getClassLoader() == loader3); 561 562 assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4); 563 assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader2); 564 assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader6); 565 566 assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6); 567 568 } 569 570 571 // -- supporting methods -- 572 573 574 /** 575 * Resolve the given modules, by name, and returns the resulting 576 * Configuration. 577 */ 578 private static Configuration resolveRequires(String... roots) { 579 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 580 return Layer.boot() 581 .configuration() 582 .resolveRequires(finder, ModuleFinder.of(), Set.of(roots)); 583 } 584 585 /** 586 * Resolve the given modules, by name, and returns the resulting 587 * Configuration. 588 */ 589 private static Configuration resolveRequiresAndUses(String... roots) { 590 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 591 return Layer.boot() 592 .configuration() 593 .resolveRequiresAndUses(finder, ModuleFinder.of(), Set.of(roots)); 594 } 595 596 597 /** 598 * Invokes the static void main(String[]) method on the given class 599 * in the given module. 600 */ 601 private static void invoke(Layer layer, String mn, String mc) throws Exception { 602 ClassLoader loader = layer.findLoader(mn); 603 Class<?> c = loader.loadClass(mc); 604 Method mainMethod = c.getMethod("main", String[].class); 605 mainMethod.invoke(null, (Object)new String[0]); 606 } 607 608 609 /** 610 * Checks that the given layer contains exactly the expected modules 611 * (by name). 612 */ 613 private void checkLayer(Layer layer, String ... expected) { 614 Set<String> names = layer.modules().stream() 615 .map(Module::getName) 616 .collect(Collectors.toSet()); 617 assertTrue(names.size() == expected.length); 618 for (String name : expected) { 619 assertTrue(names.contains(name)); 620 } 621 } 622 623 624 /** 625 * Test that a class can be loaded via the class loader of all modules 626 * in the given layer. 627 */ 628 static void testLoad(Layer layer, String cn) throws Exception { 629 for (Module m : layer.modules()) { 630 ClassLoader l = m.getClassLoader(); 631 l.loadClass(cn); 632 } 633 } 634 635 636 /** 637 * Test that a class cannot be loaded via any of the class loaders of 638 * the modules in the given layer. 639 */ 640 static void testLoadFail(Layer layer, String cn) throws Exception { 641 for (Module m : layer.modules()) { 642 ClassLoader l = m.getClassLoader(); 643 try { 644 l.loadClass(cn); 645 assertTrue(false); 646 } catch (ClassNotFoundException expected) { } 647 } 648 } 649 650 651 /** 652 * Returns a ModuleFinder that only finds the given test modules 653 */ 654 static ModuleFinder finderFor(String... names) { 655 656 ModuleFinder finder = ModuleFinder.of(MODS_DIR); 657 658 Map<String, ModuleReference> mrefs = new HashMap<>(); 659 for (String name : names) { 660 Optional<ModuleReference> omref = finder.find(name); 661 assert omref.isPresent(); 662 mrefs.put(name, omref.get()); 663 } 664 665 return new ModuleFinder() { 666 @Override 667 public Optional<ModuleReference> find(String name) { 668 ModuleReference mref = mrefs.get(name); 669 return Optional.ofNullable(mref); 670 } 671 @Override 672 public Set<ModuleReference> findAll() { 673 return mrefs.values().stream().collect(Collectors.toSet()); 674 } 675 }; 676 } 677 678 }