1 /* 2 * Copyright (c) 2014, 2020, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.lang; 27 28 import java.io.IOException; 29 import java.io.InputStream; 30 import java.lang.annotation.Annotation; 31 import java.lang.module.Configuration; 32 import java.lang.module.ModuleReference; 33 import java.lang.module.ModuleDescriptor; 34 import java.lang.module.ModuleDescriptor.Exports; 35 import java.lang.module.ModuleDescriptor.Opens; 36 import java.lang.module.ModuleDescriptor.Version; 37 import java.lang.module.ResolvedModule; 38 import java.lang.reflect.AnnotatedElement; 39 import java.net.URI; 40 import java.net.URL; 41 import java.security.AccessController; 42 import java.security.PrivilegedAction; 43 import java.util.HashMap; 44 import java.util.HashSet; 45 import java.util.List; 46 import java.util.Map; 47 import java.util.Objects; 48 import java.util.Optional; 49 import java.util.Set; 50 import java.util.concurrent.ConcurrentHashMap; 51 import java.util.function.Function; 52 import java.util.stream.Collectors; 53 import java.util.stream.Stream; 54 55 import jdk.internal.loader.BuiltinClassLoader; 56 import jdk.internal.loader.BootLoader; 57 import jdk.internal.loader.ClassLoaders; 58 import jdk.internal.misc.VM; 59 import jdk.internal.module.IllegalAccessLogger; 60 import jdk.internal.module.ModuleLoaderMap; 61 import jdk.internal.module.ServicesCatalog; 62 import jdk.internal.module.Resources; 63 import jdk.internal.org.objectweb.asm.AnnotationVisitor; 64 import jdk.internal.org.objectweb.asm.Attribute; 65 import jdk.internal.org.objectweb.asm.ClassReader; 66 import jdk.internal.org.objectweb.asm.ClassVisitor; 67 import jdk.internal.org.objectweb.asm.ClassWriter; 68 import jdk.internal.org.objectweb.asm.ModuleVisitor; 69 import jdk.internal.org.objectweb.asm.Opcodes; 70 import jdk.internal.reflect.CallerSensitive; 71 import jdk.internal.reflect.Reflection; 72 import sun.security.util.SecurityConstants; 73 74 /** 75 * Represents a run-time module, either {@link #isNamed() named} or unnamed. 76 * 77 * <p> Named modules have a {@link #getName() name} and are constructed by the 78 * Java Virtual Machine when a graph of modules is defined to the Java virtual 79 * machine to create a {@linkplain ModuleLayer module layer}. </p> 80 * 81 * <p> An unnamed module does not have a name. There is an unnamed module for 82 * each {@link ClassLoader ClassLoader}, obtained by invoking its {@link 83 * ClassLoader#getUnnamedModule() getUnnamedModule} method. All types that are 84 * not in a named module are members of their defining class loader's unnamed 85 * module. </p> 86 * 87 * <p> The package names that are parameters or returned by methods defined in 88 * this class are the fully-qualified names of the packages as defined in 89 * section {@jls 6.5.3} of <cite>The Java Language Specification</cite>, for 90 * example, {@code "java.lang"}. </p> 91 * 92 * <p> Unless otherwise specified, passing a {@code null} argument to a method 93 * in this class causes a {@link NullPointerException NullPointerException} to 94 * be thrown. </p> 95 * 96 * @since 9 97 * @spec JPMS 98 * @see Class#getModule() 99 */ 100 101 public final class Module implements AnnotatedElement { 102 103 // the layer that contains this module, can be null 104 private final ModuleLayer layer; 105 106 // module name and loader, these fields are read by VM 107 private final String name; 108 private final ClassLoader loader; 109 110 // the module descriptor 111 private final ModuleDescriptor descriptor; 112 113 114 /** 115 * Creates a new named Module. The resulting Module will be defined to the 116 * VM but will not read any other modules, will not have any exports setup 117 * and will not be registered in the service catalog. 118 */ 119 Module(ModuleLayer layer, 120 ClassLoader loader, 121 ModuleDescriptor descriptor, 122 URI uri) 123 { 124 this.layer = layer; 125 this.name = descriptor.name(); 126 this.loader = loader; 127 this.descriptor = descriptor; 128 129 // define module to VM 130 131 boolean isOpen = descriptor.isOpen() || descriptor.isAutomatic(); 132 Version version = descriptor.version().orElse(null); 133 String vs = Objects.toString(version, null); 134 String loc = Objects.toString(uri, null); 135 Object[] packages = descriptor.packages().toArray(); 136 defineModule0(this, isOpen, vs, loc, packages); 137 } 138 139 140 /** 141 * Create the unnamed Module for the given ClassLoader. 142 * 143 * @see ClassLoader#getUnnamedModule 144 */ 145 Module(ClassLoader loader) { 146 this.layer = null; 147 this.name = null; 148 this.loader = loader; 149 this.descriptor = null; 150 } 151 152 153 /** 154 * Creates a named module but without defining the module to the VM. 155 * 156 * @apiNote This constructor is for VM white-box testing. 157 */ 158 Module(ClassLoader loader, ModuleDescriptor descriptor) { 159 this.layer = null; 160 this.name = descriptor.name(); 161 this.loader = loader; 162 this.descriptor = descriptor; 163 } 164 165 166 /** 167 * Returns {@code true} if this module is a named module. 168 * 169 * @return {@code true} if this is a named module 170 * 171 * @see ClassLoader#getUnnamedModule() 172 */ 173 public boolean isNamed() { 174 return name != null; 175 } 176 177 /** 178 * Returns the module name or {@code null} if this module is an unnamed 179 * module. 180 * 181 * @return The module name 182 */ 183 public String getName() { 184 return name; 185 } 186 187 /** 188 * Returns the {@code ClassLoader} for this module. 189 * 190 * <p> If there is a security manager then its {@code checkPermission} 191 * method if first called with a {@code RuntimePermission("getClassLoader")} 192 * permission to check that the caller is allowed to get access to the 193 * class loader. </p> 194 * 195 * @return The class loader for this module 196 * 197 * @throws SecurityException 198 * If denied by the security manager 199 */ 200 public ClassLoader getClassLoader() { 201 SecurityManager sm = System.getSecurityManager(); 202 if (sm != null) { 203 sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION); 204 } 205 return loader; 206 } 207 208 /** 209 * Returns the module descriptor for this module or {@code null} if this 210 * module is an unnamed module. 211 * 212 * @return The module descriptor for this module 213 */ 214 public ModuleDescriptor getDescriptor() { 215 return descriptor; 216 } 217 218 /** 219 * Returns the module layer that contains this module or {@code null} if 220 * this module is not in a module layer. 221 * 222 * A module layer contains named modules and therefore this method always 223 * returns {@code null} when invoked on an unnamed module. 224 * 225 * <p> <a href="reflect/Proxy.html#dynamicmodule">Dynamic modules</a> are 226 * named modules that are generated at runtime. A dynamic module may or may 227 * not be in a module layer. </p> 228 * 229 * @return The module layer that contains this module 230 * 231 * @see java.lang.reflect.Proxy 232 */ 233 public ModuleLayer getLayer() { 234 if (isNamed()) { 235 ModuleLayer layer = this.layer; 236 if (layer != null) 237 return layer; 238 239 // special-case java.base as it is created before the boot layer 240 if (loader == null && name.equals("java.base")) { 241 return ModuleLayer.boot(); 242 } 243 } 244 return null; 245 } 246 247 // -- 248 249 // special Module to mean "all unnamed modules" 250 private static final Module ALL_UNNAMED_MODULE; 251 private static final Set<Module> ALL_UNNAMED_MODULE_SET; 252 253 // special Module to mean "everyone" 254 private static final Module EVERYONE_MODULE; 255 private static final Set<Module> EVERYONE_SET; 256 257 private static class ArchivedData { 258 private static ArchivedData archivedData; 259 private final Module allUnnamedModule; 260 private final Set<Module> allUnnamedModules; 261 private final Module everyoneModule; 262 private final Set<Module> everyoneSet; 263 264 private ArchivedData() { 265 this.allUnnamedModule = ALL_UNNAMED_MODULE; 266 this.allUnnamedModules = ALL_UNNAMED_MODULE_SET; 267 this.everyoneModule = EVERYONE_MODULE; 268 this.everyoneSet = EVERYONE_SET; 269 } 270 271 static void archive() { 272 archivedData = new ArchivedData(); 273 } 274 275 static ArchivedData get() { 276 return archivedData; 277 } 278 279 static { 280 VM.initializeFromArchive(ArchivedData.class); 281 } 282 } 283 284 static { 285 ArchivedData archivedData = ArchivedData.get(); 286 if (archivedData != null) { 287 ALL_UNNAMED_MODULE = archivedData.allUnnamedModule; 288 ALL_UNNAMED_MODULE_SET = archivedData.allUnnamedModules; 289 EVERYONE_MODULE = archivedData.everyoneModule; 290 EVERYONE_SET = archivedData.everyoneSet; 291 } else { 292 ALL_UNNAMED_MODULE = new Module(null); 293 ALL_UNNAMED_MODULE_SET = Set.of(ALL_UNNAMED_MODULE); 294 EVERYONE_MODULE = new Module(null); 295 EVERYONE_SET = Set.of(EVERYONE_MODULE); 296 ArchivedData.archive(); 297 } 298 } 299 300 /** 301 * The holder of data structures to support readability, exports, and 302 * service use added at runtime with the reflective APIs. 303 */ 304 private static class ReflectionData { 305 /** 306 * A module (1st key) reads another module (2nd key) 307 */ 308 static final WeakPairMap<Module, Module, Boolean> reads = 309 new WeakPairMap<>(); 310 311 /** 312 * A module (1st key) exports or opens a package to another module 313 * (2nd key). The map value is a map of package name to a boolean 314 * that indicates if the package is opened. 315 */ 316 static final WeakPairMap<Module, Module, Map<String, Boolean>> exports = 317 new WeakPairMap<>(); 318 319 /** 320 * A module (1st key) uses a service (2nd key) 321 */ 322 static final WeakPairMap<Module, Class<?>, Boolean> uses = 323 new WeakPairMap<>(); 324 } 325 326 327 // -- readability -- 328 329 // the modules that this module reads 330 private volatile Set<Module> reads; 331 332 /** 333 * Indicates if this module reads the given module. This method returns 334 * {@code true} if invoked to test if this module reads itself. It also 335 * returns {@code true} if invoked on an unnamed module (as unnamed 336 * modules read all modules). 337 * 338 * @param other 339 * The other module 340 * 341 * @return {@code true} if this module reads {@code other} 342 * 343 * @see #addReads(Module) 344 */ 345 public boolean canRead(Module other) { 346 Objects.requireNonNull(other); 347 348 // an unnamed module reads all modules 349 if (!this.isNamed()) 350 return true; 351 352 // all modules read themselves 353 if (other == this) 354 return true; 355 356 // check if this module reads other 357 if (other.isNamed()) { 358 Set<Module> reads = this.reads; // volatile read 359 if (reads != null && reads.contains(other)) 360 return true; 361 } 362 363 // check if this module reads the other module reflectively 364 if (ReflectionData.reads.containsKeyPair(this, other)) 365 return true; 366 367 // if other is an unnamed module then check if this module reads 368 // all unnamed modules 369 if (!other.isNamed() 370 && ReflectionData.reads.containsKeyPair(this, ALL_UNNAMED_MODULE)) 371 return true; 372 373 return false; 374 } 375 376 /** 377 * If the caller's module is this module then update this module to read 378 * the given module. 379 * 380 * This method is a no-op if {@code other} is this module (all modules read 381 * themselves), this module is an unnamed module (as unnamed modules read 382 * all modules), or this module already reads {@code other}. 383 * 384 * @implNote <em>Read edges</em> added by this method are <em>weak</em> and 385 * do not prevent {@code other} from being GC'ed when this module is 386 * strongly reachable. 387 * 388 * @param other 389 * The other module 390 * 391 * @return this module 392 * 393 * @throws IllegalCallerException 394 * If this is a named module and the caller's module is not this 395 * module 396 * 397 * @see #canRead 398 */ 399 @CallerSensitive 400 public Module addReads(Module other) { 401 Objects.requireNonNull(other); 402 if (this.isNamed()) { 403 Module caller = getCallerModule(Reflection.getCallerClass()); 404 if (caller != this) { 405 throw new IllegalCallerException(caller + " != " + this); 406 } 407 implAddReads(other, true); 408 } 409 return this; 410 } 411 412 /** 413 * Updates this module to read another module. 414 * 415 * @apiNote Used by the --add-reads command line option. 416 */ 417 void implAddReads(Module other) { 418 implAddReads(other, true); 419 } 420 421 /** 422 * Updates this module to read all unnamed modules. 423 * 424 * @apiNote Used by the --add-reads command line option. 425 */ 426 void implAddReadsAllUnnamed() { 427 implAddReads(Module.ALL_UNNAMED_MODULE, true); 428 } 429 430 /** 431 * Updates this module to read another module without notifying the VM. 432 * 433 * @apiNote This method is for VM white-box testing. 434 */ 435 void implAddReadsNoSync(Module other) { 436 implAddReads(other, false); 437 } 438 439 /** 440 * Makes the given {@code Module} readable to this module. 441 * 442 * If {@code syncVM} is {@code true} then the VM is notified. 443 */ 444 private void implAddReads(Module other, boolean syncVM) { 445 Objects.requireNonNull(other); 446 if (!canRead(other)) { 447 // update VM first, just in case it fails 448 if (syncVM) { 449 if (other == ALL_UNNAMED_MODULE) { 450 addReads0(this, null); 451 } else { 452 addReads0(this, other); 453 } 454 } 455 456 // add reflective read 457 ReflectionData.reads.putIfAbsent(this, other, Boolean.TRUE); 458 } 459 } 460 461 462 // -- exported and open packages -- 463 464 // the packages are open to other modules, can be null 465 // if the value contains EVERYONE_MODULE then the package is open to all 466 private volatile Map<String, Set<Module>> openPackages; 467 468 // the packages that are exported, can be null 469 // if the value contains EVERYONE_MODULE then the package is exported to all 470 private volatile Map<String, Set<Module>> exportedPackages; 471 472 /** 473 * Returns {@code true} if this module exports the given package to at 474 * least the given module. 475 * 476 * <p> This method returns {@code true} if invoked to test if a package in 477 * this module is exported to itself. It always returns {@code true} when 478 * invoked on an unnamed module. A package that is {@link #isOpen open} to 479 * the given module is considered exported to that module at run-time and 480 * so this method returns {@code true} if the package is open to the given 481 * module. </p> 482 * 483 * <p> This method does not check if the given module reads this module. </p> 484 * 485 * @param pn 486 * The package name 487 * @param other 488 * The other module 489 * 490 * @return {@code true} if this module exports the package to at least the 491 * given module 492 * 493 * @see ModuleDescriptor#exports() 494 * @see #addExports(String,Module) 495 */ 496 public boolean isExported(String pn, Module other) { 497 Objects.requireNonNull(pn); 498 Objects.requireNonNull(other); 499 return implIsExportedOrOpen(pn, other, /*open*/false); 500 } 501 502 /** 503 * Returns {@code true} if this module has <em>opened</em> a package to at 504 * least the given module. 505 * 506 * <p> This method returns {@code true} if invoked to test if a package in 507 * this module is open to itself. It returns {@code true} when invoked on an 508 * {@link ModuleDescriptor#isOpen open} module with a package in the module. 509 * It always returns {@code true} when invoked on an unnamed module. </p> 510 * 511 * <p> This method does not check if the given module reads this module. </p> 512 * 513 * @param pn 514 * The package name 515 * @param other 516 * The other module 517 * 518 * @return {@code true} if this module has <em>opened</em> the package 519 * to at least the given module 520 * 521 * @see ModuleDescriptor#opens() 522 * @see #addOpens(String,Module) 523 * @see java.lang.reflect.AccessibleObject#setAccessible(boolean) 524 * @see java.lang.invoke.MethodHandles#privateLookupIn 525 */ 526 public boolean isOpen(String pn, Module other) { 527 Objects.requireNonNull(pn); 528 Objects.requireNonNull(other); 529 return implIsExportedOrOpen(pn, other, /*open*/true); 530 } 531 532 /** 533 * Returns {@code true} if this module exports the given package 534 * unconditionally. 535 * 536 * <p> This method always returns {@code true} when invoked on an unnamed 537 * module. A package that is {@link #isOpen(String) opened} unconditionally 538 * is considered exported unconditionally at run-time and so this method 539 * returns {@code true} if the package is opened unconditionally. </p> 540 * 541 * <p> This method does not check if the given module reads this module. </p> 542 * 543 * @param pn 544 * The package name 545 * 546 * @return {@code true} if this module exports the package unconditionally 547 * 548 * @see ModuleDescriptor#exports() 549 */ 550 public boolean isExported(String pn) { 551 Objects.requireNonNull(pn); 552 return implIsExportedOrOpen(pn, EVERYONE_MODULE, /*open*/false); 553 } 554 555 /** 556 * Returns {@code true} if this module has <em>opened</em> a package 557 * unconditionally. 558 * 559 * <p> This method always returns {@code true} when invoked on an unnamed 560 * module. Additionally, it always returns {@code true} when invoked on an 561 * {@link ModuleDescriptor#isOpen open} module with a package in the 562 * module. </p> 563 * 564 * <p> This method does not check if the given module reads this module. </p> 565 * 566 * @param pn 567 * The package name 568 * 569 * @return {@code true} if this module has <em>opened</em> the package 570 * unconditionally 571 * 572 * @see ModuleDescriptor#opens() 573 */ 574 public boolean isOpen(String pn) { 575 Objects.requireNonNull(pn); 576 return implIsExportedOrOpen(pn, EVERYONE_MODULE, /*open*/true); 577 } 578 579 580 /** 581 * Returns {@code true} if this module exports or opens the given package 582 * to the given module. If the other module is {@code EVERYONE_MODULE} then 583 * this method tests if the package is exported or opened unconditionally. 584 */ 585 private boolean implIsExportedOrOpen(String pn, Module other, boolean open) { 586 // all packages in unnamed modules are open 587 if (!isNamed()) 588 return true; 589 590 // all packages are exported/open to self 591 if (other == this && descriptor.packages().contains(pn)) 592 return true; 593 594 // all packages in open and automatic modules are open 595 if (descriptor.isOpen() || descriptor.isAutomatic()) 596 return descriptor.packages().contains(pn); 597 598 // exported/opened via module declaration/descriptor 599 if (isStaticallyExportedOrOpen(pn, other, open)) 600 return true; 601 602 // exported via addExports/addOpens 603 if (isReflectivelyExportedOrOpen(pn, other, open)) 604 return true; 605 606 // not exported or open to other 607 return false; 608 } 609 610 /** 611 * Returns {@code true} if this module exports or opens a package to 612 * the given module via its module declaration or CLI options. 613 */ 614 private boolean isStaticallyExportedOrOpen(String pn, Module other, boolean open) { 615 // test if package is open to everyone or <other> 616 Map<String, Set<Module>> openPackages = this.openPackages; 617 if (openPackages != null && allows(openPackages.get(pn), other)) { 618 return true; 619 } 620 621 if (!open) { 622 // test package is exported to everyone or <other> 623 Map<String, Set<Module>> exportedPackages = this.exportedPackages; 624 if (exportedPackages != null && allows(exportedPackages.get(pn), other)) { 625 return true; 626 } 627 } 628 629 return false; 630 } 631 632 /** 633 * Returns {@code true} if targets is non-null and contains EVERYONE_MODULE 634 * or the given module. Also returns true if the given module is an unnamed 635 * module and targets contains ALL_UNNAMED_MODULE. 636 */ 637 private boolean allows(Set<Module> targets, Module module) { 638 if (targets != null) { 639 if (targets.contains(EVERYONE_MODULE)) 640 return true; 641 if (module != EVERYONE_MODULE) { 642 if (targets.contains(module)) 643 return true; 644 if (!module.isNamed() && targets.contains(ALL_UNNAMED_MODULE)) 645 return true; 646 } 647 } 648 return false; 649 } 650 651 /** 652 * Returns {@code true} if this module reflectively exports or opens the 653 * given package to the given module. 654 */ 655 private boolean isReflectivelyExportedOrOpen(String pn, Module other, boolean open) { 656 // exported or open to all modules 657 Map<String, Boolean> exports = ReflectionData.exports.get(this, EVERYONE_MODULE); 658 if (exports != null) { 659 Boolean b = exports.get(pn); 660 if (b != null) { 661 boolean isOpen = b.booleanValue(); 662 if (!open || isOpen) return true; 663 } 664 } 665 666 if (other != EVERYONE_MODULE) { 667 668 // exported or open to other 669 exports = ReflectionData.exports.get(this, other); 670 if (exports != null) { 671 Boolean b = exports.get(pn); 672 if (b != null) { 673 boolean isOpen = b.booleanValue(); 674 if (!open || isOpen) return true; 675 } 676 } 677 678 // other is an unnamed module && exported or open to all unnamed 679 if (!other.isNamed()) { 680 exports = ReflectionData.exports.get(this, ALL_UNNAMED_MODULE); 681 if (exports != null) { 682 Boolean b = exports.get(pn); 683 if (b != null) { 684 boolean isOpen = b.booleanValue(); 685 if (!open || isOpen) return true; 686 } 687 } 688 } 689 690 } 691 692 return false; 693 } 694 695 /** 696 * Returns {@code true} if this module reflectively exports the 697 * given package to the given module. 698 */ 699 boolean isReflectivelyExported(String pn, Module other) { 700 return isReflectivelyExportedOrOpen(pn, other, false); 701 } 702 703 /** 704 * Returns {@code true} if this module reflectively opens the 705 * given package to the given module. 706 */ 707 boolean isReflectivelyOpened(String pn, Module other) { 708 return isReflectivelyExportedOrOpen(pn, other, true); 709 } 710 711 712 /** 713 * If the caller's module is this module then update this module to export 714 * the given package to the given module. 715 * 716 * <p> This method has no effect if the package is already exported (or 717 * <em>open</em>) to the given module. </p> 718 * 719 * @apiNote As specified in section {@jvms 5.4.3} of the <cite>The Java 720 * Virtual Machine Specification </cite>, if an attempt to resolve a 721 * symbolic reference fails because of a linkage error, then subsequent 722 * attempts to resolve the reference always fail with the same error that 723 * was thrown as a result of the initial resolution attempt. 724 * 725 * @param pn 726 * The package name 727 * @param other 728 * The module 729 * 730 * @return this module 731 * 732 * @throws IllegalArgumentException 733 * If {@code pn} is {@code null}, or this is a named module and the 734 * package {@code pn} is not a package in this module 735 * @throws IllegalCallerException 736 * If this is a named module and the caller's module is not this 737 * module 738 * 739 * @jvms 5.4.3 Resolution 740 * @see #isExported(String,Module) 741 */ 742 @CallerSensitive 743 public Module addExports(String pn, Module other) { 744 if (pn == null) 745 throw new IllegalArgumentException("package is null"); 746 Objects.requireNonNull(other); 747 748 if (isNamed()) { 749 Module caller = getCallerModule(Reflection.getCallerClass()); 750 if (caller != this) { 751 throw new IllegalCallerException(caller + " != " + this); 752 } 753 implAddExportsOrOpens(pn, other, /*open*/false, /*syncVM*/true); 754 } 755 756 return this; 757 } 758 759 /** 760 * If this module has <em>opened</em> a package to at least the caller 761 * module then update this module to open the package to the given module. 762 * Opening a package with this method allows all types in the package, 763 * and all their members, not just public types and their public members, 764 * to be reflected on by the given module when using APIs that support 765 * private access or a way to bypass or suppress default Java language 766 * access control checks. 767 * 768 * <p> This method has no effect if the package is already <em>open</em> 769 * to the given module. </p> 770 * 771 * @apiNote This method can be used for cases where a <em>consumer 772 * module</em> uses a qualified opens to open a package to an <em>API 773 * module</em> but where the reflective access to the members of classes in 774 * the consumer module is delegated to code in another module. Code in the 775 * API module can use this method to open the package in the consumer module 776 * to the other module. 777 * 778 * @param pn 779 * The package name 780 * @param other 781 * The module 782 * 783 * @return this module 784 * 785 * @throws IllegalArgumentException 786 * If {@code pn} is {@code null}, or this is a named module and the 787 * package {@code pn} is not a package in this module 788 * @throws IllegalCallerException 789 * If this is a named module and this module has not opened the 790 * package to at least the caller's module 791 * 792 * @see #isOpen(String,Module) 793 * @see java.lang.reflect.AccessibleObject#setAccessible(boolean) 794 * @see java.lang.invoke.MethodHandles#privateLookupIn 795 */ 796 @CallerSensitive 797 public Module addOpens(String pn, Module other) { 798 if (pn == null) 799 throw new IllegalArgumentException("package is null"); 800 Objects.requireNonNull(other); 801 802 if (isNamed()) { 803 Module caller = getCallerModule(Reflection.getCallerClass()); 804 if (caller != this && (caller == null || !isOpen(pn, caller))) 805 throw new IllegalCallerException(pn + " is not open to " + caller); 806 implAddExportsOrOpens(pn, other, /*open*/true, /*syncVM*/true); 807 } 808 809 return this; 810 } 811 812 813 /** 814 * Updates this module to export a package unconditionally. 815 * 816 * @apiNote This method is for JDK tests only. 817 */ 818 void implAddExports(String pn) { 819 implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, false, true); 820 } 821 822 /** 823 * Updates this module to export a package to another module. 824 * 825 * @apiNote Used by Instrumentation::redefineModule and --add-exports 826 */ 827 void implAddExports(String pn, Module other) { 828 implAddExportsOrOpens(pn, other, false, true); 829 } 830 831 /** 832 * Updates this module to export a package to all unnamed modules. 833 * 834 * @apiNote Used by the --add-exports command line option. 835 */ 836 void implAddExportsToAllUnnamed(String pn) { 837 implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, false, true); 838 } 839 840 /** 841 * Updates this export to export a package unconditionally without 842 * notifying the VM. 843 * 844 * @apiNote This method is for VM white-box testing. 845 */ 846 void implAddExportsNoSync(String pn) { 847 implAddExportsOrOpens(pn.replace('/', '.'), Module.EVERYONE_MODULE, false, false); 848 } 849 850 /** 851 * Updates a module to export a package to another module without 852 * notifying the VM. 853 * 854 * @apiNote This method is for VM white-box testing. 855 */ 856 void implAddExportsNoSync(String pn, Module other) { 857 implAddExportsOrOpens(pn.replace('/', '.'), other, false, false); 858 } 859 860 /** 861 * Updates this module to open a package unconditionally. 862 * 863 * @apiNote This method is for JDK tests only. 864 */ 865 void implAddOpens(String pn) { 866 implAddExportsOrOpens(pn, Module.EVERYONE_MODULE, true, true); 867 } 868 869 /** 870 * Updates this module to open a package to another module. 871 * 872 * @apiNote Used by Instrumentation::redefineModule and --add-opens 873 */ 874 void implAddOpens(String pn, Module other) { 875 implAddExportsOrOpens(pn, other, true, true); 876 } 877 878 /** 879 * Updates this module to open a package to all unnamed modules. 880 * 881 * @apiNote Used by the --add-opens command line option. 882 */ 883 void implAddOpensToAllUnnamed(String pn) { 884 implAddExportsOrOpens(pn, Module.ALL_UNNAMED_MODULE, true, true); 885 } 886 887 /** 888 * Updates a module to export or open a module to another module. 889 * 890 * If {@code syncVM} is {@code true} then the VM is notified. 891 */ 892 private void implAddExportsOrOpens(String pn, 893 Module other, 894 boolean open, 895 boolean syncVM) { 896 Objects.requireNonNull(other); 897 Objects.requireNonNull(pn); 898 899 // all packages are open in unnamed, open, and automatic modules 900 if (!isNamed() || descriptor.isOpen() || descriptor.isAutomatic()) 901 return; 902 903 // check if the package is already exported/open to other 904 if (implIsExportedOrOpen(pn, other, open)) { 905 906 // if the package is exported/open for illegal access then we need 907 // to record that it has also been exported/opened reflectively so 908 // that the IllegalAccessLogger doesn't emit a warning. 909 boolean needToAdd = false; 910 if (!other.isNamed()) { 911 IllegalAccessLogger l = IllegalAccessLogger.illegalAccessLogger(); 912 if (l != null) { 913 if (open) { 914 needToAdd = l.isOpenForIllegalAccess(this, pn); 915 } else { 916 needToAdd = l.isExportedForIllegalAccess(this, pn); 917 } 918 } 919 } 920 if (!needToAdd) { 921 // nothing to do 922 return; 923 } 924 } 925 926 // can only export a package in the module 927 if (!descriptor.packages().contains(pn)) { 928 throw new IllegalArgumentException("package " + pn 929 + " not in contents"); 930 } 931 932 // update VM first, just in case it fails 933 if (syncVM) { 934 if (other == EVERYONE_MODULE) { 935 addExportsToAll0(this, pn); 936 } else if (other == ALL_UNNAMED_MODULE) { 937 addExportsToAllUnnamed0(this, pn); 938 } else { 939 addExports0(this, pn, other); 940 } 941 } 942 943 // add package name to exports if absent 944 Map<String, Boolean> map = ReflectionData.exports 945 .computeIfAbsent(this, other, 946 (m1, m2) -> new ConcurrentHashMap<>()); 947 if (open) { 948 map.put(pn, Boolean.TRUE); // may need to promote from FALSE to TRUE 949 } else { 950 map.putIfAbsent(pn, Boolean.FALSE); 951 } 952 } 953 954 /** 955 * Updates a module to open all packages in the given sets to all unnamed 956 * modules. 957 * 958 * @apiNote Used during startup to open packages for illegal access. 959 */ 960 void implAddOpensToAllUnnamed(Set<String> concealedPkgs, Set<String> exportedPkgs) { 961 if (jdk.internal.misc.VM.isModuleSystemInited()) { 962 throw new IllegalStateException("Module system already initialized"); 963 } 964 965 // replace this module's openPackages map with a new map that opens 966 // the packages to all unnamed modules. 967 Map<String, Set<Module>> openPackages = this.openPackages; 968 if (openPackages == null) { 969 openPackages = new HashMap<>((4 * (concealedPkgs.size() + exportedPkgs.size()) / 3) + 1); 970 } else { 971 openPackages = new HashMap<>(openPackages); 972 } 973 implAddOpensToAllUnnamed(concealedPkgs, openPackages); 974 implAddOpensToAllUnnamed(exportedPkgs, openPackages); 975 this.openPackages = openPackages; 976 } 977 978 private void implAddOpensToAllUnnamed(Set<String> pkgs, Map<String, Set<Module>> openPackages) { 979 for (String pn : pkgs) { 980 Set<Module> prev = openPackages.putIfAbsent(pn, ALL_UNNAMED_MODULE_SET); 981 if (prev != null) { 982 prev.add(ALL_UNNAMED_MODULE); 983 } 984 985 // update VM to export the package 986 addExportsToAllUnnamed0(this, pn); 987 } 988 } 989 990 // -- services -- 991 992 /** 993 * If the caller's module is this module then update this module to add a 994 * service dependence on the given service type. This method is intended 995 * for use by frameworks that invoke {@link java.util.ServiceLoader 996 * ServiceLoader} on behalf of other modules or where the framework is 997 * passed a reference to the service type by other code. This method is 998 * a no-op when invoked on an unnamed module or an automatic module. 999 * 1000 * <p> This method does not cause {@link Configuration#resolveAndBind 1001 * resolveAndBind} to be re-run. </p> 1002 * 1003 * @param service 1004 * The service type 1005 * 1006 * @return this module 1007 * 1008 * @throws IllegalCallerException 1009 * If this is a named module and the caller's module is not this 1010 * module 1011 * 1012 * @see #canUse(Class) 1013 * @see ModuleDescriptor#uses() 1014 */ 1015 @CallerSensitive 1016 public Module addUses(Class<?> service) { 1017 Objects.requireNonNull(service); 1018 1019 if (isNamed() && !descriptor.isAutomatic()) { 1020 Module caller = getCallerModule(Reflection.getCallerClass()); 1021 if (caller != this) { 1022 throw new IllegalCallerException(caller + " != " + this); 1023 } 1024 implAddUses(service); 1025 } 1026 1027 return this; 1028 } 1029 1030 /** 1031 * Update this module to add a service dependence on the given service 1032 * type. 1033 */ 1034 void implAddUses(Class<?> service) { 1035 if (!canUse(service)) { 1036 ReflectionData.uses.putIfAbsent(this, service, Boolean.TRUE); 1037 } 1038 } 1039 1040 1041 /** 1042 * Indicates if this module has a service dependence on the given service 1043 * type. This method always returns {@code true} when invoked on an unnamed 1044 * module or an automatic module. 1045 * 1046 * @param service 1047 * The service type 1048 * 1049 * @return {@code true} if this module uses service type {@code st} 1050 * 1051 * @see #addUses(Class) 1052 */ 1053 public boolean canUse(Class<?> service) { 1054 Objects.requireNonNull(service); 1055 1056 if (!isNamed()) 1057 return true; 1058 1059 if (descriptor.isAutomatic()) 1060 return true; 1061 1062 // uses was declared 1063 if (descriptor.uses().contains(service.getName())) 1064 return true; 1065 1066 // uses added via addUses 1067 return ReflectionData.uses.containsKeyPair(this, service); 1068 } 1069 1070 1071 1072 // -- packages -- 1073 1074 /** 1075 * Returns the set of package names for the packages in this module. 1076 * 1077 * <p> For named modules, the returned set contains an element for each 1078 * package in the module. </p> 1079 * 1080 * <p> For unnamed modules, this method is the equivalent to invoking the 1081 * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of 1082 * this module's class loader and returning the set of package names. </p> 1083 * 1084 * @return the set of the package names of the packages in this module 1085 */ 1086 public Set<String> getPackages() { 1087 if (isNamed()) { 1088 return descriptor.packages(); 1089 } else { 1090 // unnamed module 1091 Stream<Package> packages; 1092 if (loader == null) { 1093 packages = BootLoader.packages(); 1094 } else { 1095 packages = loader.packages(); 1096 } 1097 return packages.map(Package::getName).collect(Collectors.toSet()); 1098 } 1099 } 1100 1101 1102 // -- creating Module objects -- 1103 1104 /** 1105 * Defines all module in a configuration to the runtime. 1106 * 1107 * @return a map of module name to runtime {@code Module} 1108 * 1109 * @throws IllegalArgumentException 1110 * If the function maps a module to the null or platform class loader 1111 * @throws IllegalStateException 1112 * If the module cannot be defined to the VM or its packages overlap 1113 * with another module mapped to the same class loader 1114 */ 1115 static Map<String, Module> defineModules(Configuration cf, 1116 Function<String, ClassLoader> clf, 1117 ModuleLayer layer) 1118 { 1119 boolean isBootLayer = (ModuleLayer.boot() == null); 1120 1121 int numModules = cf.modules().size(); 1122 int cap = (int)(numModules / 0.75f + 1.0f); 1123 Map<String, Module> nameToModule = new HashMap<>(cap); 1124 1125 // to avoid repeated lookups and reduce iteration overhead, we create 1126 // arrays holding correlated information about each module. 1127 ResolvedModule[] resolvedModules = new ResolvedModule[numModules]; 1128 Module[] modules = new Module[numModules]; 1129 ClassLoader[] classLoaders = new ClassLoader[numModules]; 1130 1131 resolvedModules = cf.modules().toArray(resolvedModules); 1132 1133 // record that we want to bind the layer to non-boot and non-platform 1134 // module loaders as a final step 1135 HashSet<ClassLoader> toBindLoaders = new HashSet<>(4); 1136 boolean hasPlatformModules = false; 1137 1138 // map each module to a class loader 1139 ClassLoader pcl = ClassLoaders.platformClassLoader(); 1140 boolean isModuleLoaderMapper = ModuleLoaderMap.isBuiltinMapper(clf); 1141 1142 for (int index = 0; index < numModules; index++) { 1143 String name = resolvedModules[index].name(); 1144 ClassLoader loader = clf.apply(name); 1145 1146 if (loader == null || loader == pcl) { 1147 if (!isModuleLoaderMapper) { 1148 throw new IllegalArgumentException("loader can't be 'null'" 1149 + " or the platform class loader"); 1150 } 1151 hasPlatformModules = true; 1152 } else { 1153 toBindLoaders.add(loader); 1154 } 1155 1156 classLoaders[index] = loader; 1157 } 1158 1159 // define each module in the configuration to the VM 1160 for (int index = 0; index < numModules; index++) { 1161 ModuleReference mref = resolvedModules[index].reference(); 1162 ModuleDescriptor descriptor = mref.descriptor(); 1163 String name = descriptor.name(); 1164 ClassLoader loader = classLoaders[index]; 1165 Module m; 1166 if (loader == null && name.equals("java.base")) { 1167 // java.base is already defined to the VM 1168 m = Object.class.getModule(); 1169 } else { 1170 URI uri = mref.location().orElse(null); 1171 m = new Module(layer, loader, descriptor, uri); 1172 } 1173 nameToModule.put(name, m); 1174 modules[index] = m; 1175 } 1176 1177 // setup readability and exports/opens 1178 for (int index = 0; index < numModules; index++) { 1179 ResolvedModule resolvedModule = resolvedModules[index]; 1180 ModuleReference mref = resolvedModule.reference(); 1181 ModuleDescriptor descriptor = mref.descriptor(); 1182 Module m = modules[index]; 1183 1184 // reads 1185 Set<Module> reads = new HashSet<>(); 1186 1187 // name -> source Module when in parent layer 1188 Map<String, Module> nameToSource = Map.of(); 1189 1190 for (ResolvedModule other : resolvedModule.reads()) { 1191 Module m2 = null; 1192 if (other.configuration() == cf) { 1193 // this configuration 1194 m2 = nameToModule.get(other.name()); 1195 assert m2 != null; 1196 } else { 1197 // parent layer 1198 for (ModuleLayer parent: layer.parents()) { 1199 m2 = findModule(parent, other); 1200 if (m2 != null) 1201 break; 1202 } 1203 assert m2 != null; 1204 if (nameToSource.isEmpty()) 1205 nameToSource = new HashMap<>(); 1206 nameToSource.put(other.name(), m2); 1207 } 1208 reads.add(m2); 1209 1210 // update VM view 1211 addReads0(m, m2); 1212 } 1213 m.reads = reads; 1214 1215 // automatic modules read all unnamed modules 1216 if (descriptor.isAutomatic()) { 1217 m.implAddReads(ALL_UNNAMED_MODULE, true); 1218 } 1219 1220 // exports and opens, skipped for open and automatic 1221 if (!descriptor.isOpen() && !descriptor.isAutomatic()) { 1222 if (isBootLayer && descriptor.opens().isEmpty()) { 1223 // no open packages, no qualified exports to modules in parent layers 1224 initExports(m, nameToModule); 1225 } else { 1226 initExportsAndOpens(m, nameToSource, nameToModule, layer.parents()); 1227 } 1228 } 1229 } 1230 1231 // if there are modules defined to the boot or platform class loaders 1232 // then register the modules in the class loader's services catalog 1233 if (hasPlatformModules) { 1234 ServicesCatalog bootCatalog = BootLoader.getServicesCatalog(); 1235 ServicesCatalog pclCatalog = ServicesCatalog.getServicesCatalog(pcl); 1236 for (int index = 0; index < numModules; index++) { 1237 ResolvedModule resolvedModule = resolvedModules[index]; 1238 ModuleReference mref = resolvedModule.reference(); 1239 ModuleDescriptor descriptor = mref.descriptor(); 1240 if (!descriptor.provides().isEmpty()) { 1241 Module m = modules[index]; 1242 ClassLoader loader = classLoaders[index]; 1243 if (loader == null) { 1244 bootCatalog.register(m); 1245 } else if (loader == pcl) { 1246 pclCatalog.register(m); 1247 } 1248 } 1249 } 1250 } 1251 1252 // record that there is a layer with modules defined to the class loader 1253 for (ClassLoader loader : toBindLoaders) { 1254 layer.bindToLoader(loader); 1255 } 1256 1257 return nameToModule; 1258 } 1259 1260 /** 1261 * Find the runtime Module corresponding to the given ResolvedModule 1262 * in the given parent layer (or its parents). 1263 */ 1264 private static Module findModule(ModuleLayer parent, 1265 ResolvedModule resolvedModule) { 1266 Configuration cf = resolvedModule.configuration(); 1267 String dn = resolvedModule.name(); 1268 return parent.layers() 1269 .filter(l -> l.configuration() == cf) 1270 .findAny() 1271 .map(layer -> { 1272 Optional<Module> om = layer.findModule(dn); 1273 assert om.isPresent() : dn + " not found in layer"; 1274 Module m = om.get(); 1275 assert m.getLayer() == layer : m + " not in expected layer"; 1276 return m; 1277 }) 1278 .orElse(null); 1279 } 1280 1281 /** 1282 * Initialize/setup a module's exports. 1283 * 1284 * @param m the module 1285 * @param nameToModule map of module name to Module (for qualified exports) 1286 */ 1287 private static void initExports(Module m, Map<String, Module> nameToModule) { 1288 Map<String, Set<Module>> exportedPackages = new HashMap<>(); 1289 1290 for (Exports exports : m.getDescriptor().exports()) { 1291 String source = exports.source(); 1292 if (exports.isQualified()) { 1293 // qualified exports 1294 Set<Module> targets = new HashSet<>(); 1295 for (String target : exports.targets()) { 1296 Module m2 = nameToModule.get(target); 1297 if (m2 != null) { 1298 addExports0(m, source, m2); 1299 targets.add(m2); 1300 } 1301 } 1302 if (!targets.isEmpty()) { 1303 exportedPackages.put(source, targets); 1304 } 1305 } else { 1306 // unqualified exports 1307 addExportsToAll0(m, source); 1308 exportedPackages.put(source, EVERYONE_SET); 1309 } 1310 } 1311 1312 if (!exportedPackages.isEmpty()) 1313 m.exportedPackages = exportedPackages; 1314 } 1315 1316 /** 1317 * Initialize/setup a module's exports. 1318 * 1319 * @param m the module 1320 * @param nameToSource map of module name to Module for modules that m reads 1321 * @param nameToModule map of module name to Module for modules in the layer 1322 * under construction 1323 * @param parents the parent layers 1324 */ 1325 private static void initExportsAndOpens(Module m, 1326 Map<String, Module> nameToSource, 1327 Map<String, Module> nameToModule, 1328 List<ModuleLayer> parents) { 1329 ModuleDescriptor descriptor = m.getDescriptor(); 1330 Map<String, Set<Module>> openPackages = new HashMap<>(); 1331 Map<String, Set<Module>> exportedPackages = new HashMap<>(); 1332 1333 // process the open packages first 1334 for (Opens opens : descriptor.opens()) { 1335 String source = opens.source(); 1336 1337 if (opens.isQualified()) { 1338 // qualified opens 1339 Set<Module> targets = new HashSet<>(); 1340 for (String target : opens.targets()) { 1341 Module m2 = findModule(target, nameToSource, nameToModule, parents); 1342 if (m2 != null) { 1343 addExports0(m, source, m2); 1344 targets.add(m2); 1345 } 1346 } 1347 if (!targets.isEmpty()) { 1348 openPackages.put(source, targets); 1349 } 1350 } else { 1351 // unqualified opens 1352 addExportsToAll0(m, source); 1353 openPackages.put(source, EVERYONE_SET); 1354 } 1355 } 1356 1357 // next the exports, skipping exports when the package is open 1358 for (Exports exports : descriptor.exports()) { 1359 String source = exports.source(); 1360 1361 // skip export if package is already open to everyone 1362 Set<Module> openToTargets = openPackages.get(source); 1363 if (openToTargets != null && openToTargets.contains(EVERYONE_MODULE)) 1364 continue; 1365 1366 if (exports.isQualified()) { 1367 // qualified exports 1368 Set<Module> targets = new HashSet<>(); 1369 for (String target : exports.targets()) { 1370 Module m2 = findModule(target, nameToSource, nameToModule, parents); 1371 if (m2 != null) { 1372 // skip qualified export if already open to m2 1373 if (openToTargets == null || !openToTargets.contains(m2)) { 1374 addExports0(m, source, m2); 1375 targets.add(m2); 1376 } 1377 } 1378 } 1379 if (!targets.isEmpty()) { 1380 exportedPackages.put(source, targets); 1381 } 1382 } else { 1383 // unqualified exports 1384 addExportsToAll0(m, source); 1385 exportedPackages.put(source, EVERYONE_SET); 1386 } 1387 } 1388 1389 if (!openPackages.isEmpty()) 1390 m.openPackages = openPackages; 1391 if (!exportedPackages.isEmpty()) 1392 m.exportedPackages = exportedPackages; 1393 } 1394 1395 /** 1396 * Find the runtime Module with the given name. The module name is the 1397 * name of a target module in a qualified exports or opens directive. 1398 * 1399 * @param target The target module to find 1400 * @param nameToSource The modules in parent layers that are read 1401 * @param nameToModule The modules in the layer under construction 1402 * @param parents The parent layers 1403 */ 1404 private static Module findModule(String target, 1405 Map<String, Module> nameToSource, 1406 Map<String, Module> nameToModule, 1407 List<ModuleLayer> parents) { 1408 Module m = nameToSource.get(target); 1409 if (m == null) { 1410 m = nameToModule.get(target); 1411 if (m == null) { 1412 for (ModuleLayer parent : parents) { 1413 m = parent.findModule(target).orElse(null); 1414 if (m != null) break; 1415 } 1416 } 1417 } 1418 return m; 1419 } 1420 1421 1422 // -- annotations -- 1423 1424 /** 1425 * {@inheritDoc} 1426 * This method returns {@code null} when invoked on an unnamed module. 1427 * 1428 * <p> Note that any annotation returned by this method is a 1429 * declaration annotation. 1430 */ 1431 @Override 1432 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { 1433 return moduleInfoClass().getDeclaredAnnotation(annotationClass); 1434 } 1435 1436 /** 1437 * {@inheritDoc} 1438 * This method returns an empty array when invoked on an unnamed module. 1439 * 1440 * <p> Note that any annotations returned by this method are 1441 * declaration annotations. 1442 */ 1443 @Override 1444 public Annotation[] getAnnotations() { 1445 return moduleInfoClass().getAnnotations(); 1446 } 1447 1448 /** 1449 * {@inheritDoc} 1450 * This method returns an empty array when invoked on an unnamed module. 1451 * 1452 * <p> Note that any annotations returned by this method are 1453 * declaration annotations. 1454 */ 1455 @Override 1456 public Annotation[] getDeclaredAnnotations() { 1457 return moduleInfoClass().getDeclaredAnnotations(); 1458 } 1459 1460 // cached class file with annotations 1461 private volatile Class<?> moduleInfoClass; 1462 1463 private Class<?> moduleInfoClass() { 1464 Class<?> clazz = this.moduleInfoClass; 1465 if (clazz != null) 1466 return clazz; 1467 1468 synchronized (this) { 1469 clazz = this.moduleInfoClass; 1470 if (clazz == null) { 1471 if (isNamed()) { 1472 PrivilegedAction<Class<?>> pa = this::loadModuleInfoClass; 1473 clazz = AccessController.doPrivileged(pa); 1474 } 1475 if (clazz == null) { 1476 class DummyModuleInfo { } 1477 clazz = DummyModuleInfo.class; 1478 } 1479 this.moduleInfoClass = clazz; 1480 } 1481 return clazz; 1482 } 1483 } 1484 1485 private Class<?> loadModuleInfoClass() { 1486 Class<?> clazz = null; 1487 try (InputStream in = getResourceAsStream("module-info.class")) { 1488 if (in != null) 1489 clazz = loadModuleInfoClass(in); 1490 } catch (Exception ignore) { } 1491 return clazz; 1492 } 1493 1494 /** 1495 * Loads module-info.class as a package-private interface in a class loader 1496 * that is a child of this module's class loader. 1497 */ 1498 private Class<?> loadModuleInfoClass(InputStream in) throws IOException { 1499 final String MODULE_INFO = "module-info"; 1500 1501 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS 1502 + ClassWriter.COMPUTE_FRAMES); 1503 1504 ClassVisitor cv = new ClassVisitor(Opcodes.ASM7, cw) { 1505 @Override 1506 public void visit(int version, 1507 int access, 1508 String name, 1509 String signature, 1510 String superName, 1511 String[] interfaces) { 1512 cw.visit(version, 1513 Opcodes.ACC_INTERFACE 1514 + Opcodes.ACC_ABSTRACT 1515 + Opcodes.ACC_SYNTHETIC, 1516 MODULE_INFO, 1517 null, 1518 "java/lang/Object", 1519 null); 1520 } 1521 @Override 1522 public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 1523 // keep annotations 1524 return super.visitAnnotation(desc, visible); 1525 } 1526 @Override 1527 public void visitAttribute(Attribute attr) { 1528 // drop non-annotation attributes 1529 } 1530 @Override 1531 public ModuleVisitor visitModule(String name, int flags, String version) { 1532 // drop Module attribute 1533 return null; 1534 } 1535 }; 1536 1537 ClassReader cr = new ClassReader(in); 1538 cr.accept(cv, 0); 1539 byte[] bytes = cw.toByteArray(); 1540 1541 ClassLoader cl = new ClassLoader(loader) { 1542 @Override 1543 protected Class<?> findClass(String cn)throws ClassNotFoundException { 1544 if (cn.equals(MODULE_INFO)) { 1545 return super.defineClass(cn, bytes, 0, bytes.length); 1546 } else { 1547 throw new ClassNotFoundException(cn); 1548 } 1549 } 1550 @Override 1551 protected Class<?> loadClass(String cn, boolean resolve) 1552 throws ClassNotFoundException 1553 { 1554 synchronized (getClassLoadingLock(cn)) { 1555 Class<?> c = findLoadedClass(cn); 1556 if (c == null) { 1557 if (cn.equals(MODULE_INFO)) { 1558 c = findClass(cn); 1559 } else { 1560 c = super.loadClass(cn, resolve); 1561 } 1562 } 1563 if (resolve) 1564 resolveClass(c); 1565 return c; 1566 } 1567 } 1568 }; 1569 1570 try { 1571 return cl.loadClass(MODULE_INFO); 1572 } catch (ClassNotFoundException e) { 1573 throw new InternalError(e); 1574 } 1575 } 1576 1577 1578 // -- misc -- 1579 1580 1581 /** 1582 * Returns an input stream for reading a resource in this module. 1583 * The {@code name} parameter is a {@code '/'}-separated path name that 1584 * identifies the resource. As with {@link Class#getResourceAsStream 1585 * Class.getResourceAsStream}, this method delegates to the module's class 1586 * loader {@link ClassLoader#findResource(String,String) 1587 * findResource(String,String)} method, invoking it with the module name 1588 * (or {@code null} when the module is unnamed) and the name of the 1589 * resource. If the resource name has a leading slash then it is dropped 1590 * before delegation. 1591 * 1592 * <p> A resource in a named module may be <em>encapsulated</em> so that 1593 * it cannot be located by code in other modules. Whether a resource can be 1594 * located or not is determined as follows: </p> 1595 * 1596 * <ul> 1597 * <li> If the resource name ends with "{@code .class}" then it is not 1598 * encapsulated. </li> 1599 * 1600 * <li> A <em>package name</em> is derived from the resource name. If 1601 * the package name is a {@linkplain #getPackages() package} in the 1602 * module then the resource can only be located by the caller of this 1603 * method when the package is {@linkplain #isOpen(String,Module) open} 1604 * to at least the caller's module. If the resource is not in a 1605 * package in the module then the resource is not encapsulated. </li> 1606 * </ul> 1607 * 1608 * <p> In the above, the <em>package name</em> for a resource is derived 1609 * from the subsequence of characters that precedes the last {@code '/'} in 1610 * the name and then replacing each {@code '/'} character in the subsequence 1611 * with {@code '.'}. A leading slash is ignored when deriving the package 1612 * name. As an example, the package name derived for a resource named 1613 * "{@code a/b/c/foo.properties}" is "{@code a.b.c}". A resource name 1614 * with the name "{@code META-INF/MANIFEST.MF}" is never encapsulated 1615 * because "{@code META-INF}" is not a legal package name. </p> 1616 * 1617 * <p> This method returns {@code null} if the resource is not in this 1618 * module, the resource is encapsulated and cannot be located by the caller, 1619 * or access to the resource is denied by the security manager. </p> 1620 * 1621 * @param name 1622 * The resource name 1623 * 1624 * @return An input stream for reading the resource or {@code null} 1625 * 1626 * @throws IOException 1627 * If an I/O error occurs 1628 * 1629 * @see Class#getResourceAsStream(String) 1630 */ 1631 @CallerSensitive 1632 public InputStream getResourceAsStream(String name) throws IOException { 1633 if (name.startsWith("/")) { 1634 name = name.substring(1); 1635 } 1636 1637 if (isNamed() && Resources.canEncapsulate(name)) { 1638 Module caller = getCallerModule(Reflection.getCallerClass()); 1639 if (caller != this && caller != Object.class.getModule()) { 1640 String pn = Resources.toPackageName(name); 1641 if (getPackages().contains(pn)) { 1642 if (caller == null && !isOpen(pn)) { 1643 // no caller, package not open 1644 return null; 1645 } 1646 if (!isOpen(pn, caller)) { 1647 // package not open to caller 1648 return null; 1649 } 1650 } 1651 } 1652 } 1653 1654 String mn = this.name; 1655 1656 // special-case built-in class loaders to avoid URL connection 1657 if (loader == null) { 1658 return BootLoader.findResourceAsStream(mn, name); 1659 } else if (loader instanceof BuiltinClassLoader) { 1660 return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name); 1661 } 1662 1663 // locate resource in module 1664 URL url = loader.findResource(mn, name); 1665 if (url != null) { 1666 try { 1667 return url.openStream(); 1668 } catch (SecurityException e) { } 1669 } 1670 1671 return null; 1672 } 1673 1674 /** 1675 * Returns the string representation of this module. For a named module, 1676 * the representation is the string {@code "module"}, followed by a space, 1677 * and then the module name. For an unnamed module, the representation is 1678 * the string {@code "unnamed module"}, followed by a space, and then an 1679 * implementation specific string that identifies the unnamed module. 1680 * 1681 * @return The string representation of this module 1682 */ 1683 @Override 1684 public String toString() { 1685 if (isNamed()) { 1686 return "module " + name; 1687 } else { 1688 String id = Integer.toHexString(System.identityHashCode(this)); 1689 return "unnamed module @" + id; 1690 } 1691 } 1692 1693 /** 1694 * Returns the module that a given caller class is a member of. Returns 1695 * {@code null} if the caller is {@code null}. 1696 */ 1697 private Module getCallerModule(Class<?> caller) { 1698 return (caller != null) ? caller.getModule() : null; 1699 } 1700 1701 1702 // -- native methods -- 1703 1704 // JVM_DefineModule 1705 private static native void defineModule0(Module module, 1706 boolean isOpen, 1707 String version, 1708 String location, 1709 Object[] pns); 1710 1711 // JVM_AddReadsModule 1712 private static native void addReads0(Module from, Module to); 1713 1714 // JVM_AddModuleExports 1715 private static native void addExports0(Module from, String pn, Module to); 1716 1717 // JVM_AddModuleExportsToAll 1718 private static native void addExportsToAll0(Module from, String pn); 1719 1720 // JVM_AddModuleExportsToAllUnnamed 1721 private static native void addExportsToAllUnnamed0(Module from, String pn); 1722 }