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