1 /*
   2  * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  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.reflect;
  27 
  28 import java.io.IOException;
  29 import java.io.InputStream;
  30 import java.lang.module.Configuration;
  31 import java.lang.module.ModuleReference;
  32 import java.lang.module.ModuleDescriptor;
  33 import java.lang.module.ModuleDescriptor.Exports;
  34 import java.lang.module.ModuleDescriptor.Provides;
  35 import java.lang.module.ModuleDescriptor.Version;
  36 import java.lang.module.ResolvedModule;
  37 import java.net.URI;
  38 import java.net.URL;
  39 import java.util.Collections;
  40 import java.util.HashMap;
  41 import java.util.HashSet;
  42 import java.util.Map;
  43 import java.util.Objects;
  44 import java.util.Optional;
  45 import java.util.Set;
  46 import java.util.function.Function;
  47 import java.util.stream.Stream;
  48 
  49 import jdk.internal.loader.BuiltinClassLoader;
  50 import jdk.internal.loader.BootLoader;
  51 import jdk.internal.misc.JavaLangReflectModuleAccess;
  52 import jdk.internal.misc.SharedSecrets;
  53 import jdk.internal.module.ServicesCatalog;
  54 import sun.reflect.CallerSensitive;
  55 import sun.reflect.Reflection;
  56 import sun.security.util.SecurityConstants;
  57 
  58 /**
  59  * Represents a run-time module, either {@link #isNamed() named} or unnamed.
  60  *
  61  * <p> Named modules have a {@link #getName() name} and are constructed by the
  62  * Java Virtual Machine when a graph of modules is defined to the Java virtual
  63  * machine to create a module {@link Layer Layer}. </p>
  64  *
  65  * <p> An unnamed module does not have a name. There is an unnamed module
  66  * per {@link ClassLoader ClassLoader} that is obtained by invoking the class
  67  * loader's {@link ClassLoader#getUnnamedModule() getUnnamedModule} method. The
  68  * {@link Class#getModule() getModule} method of all types defined by a class
  69  * loader that are not in a named module return the class loader's unnamed
  70  * module. </p>
  71  *
  72  * <p> The package names that are parameters or returned by methods defined in
  73  * this class are the fully-qualified names of the packages as defined in
  74  * section 6.5.3 of <cite>The Java&trade; Language Specification </cite>, for
  75  * example, {@code "java.lang"}. </p>
  76  *
  77  * <p> Unless otherwise specified, passing a {@code null} argument to a method
  78  * in this class causes a {@link NullPointerException NullPointerException} to
  79  * be thrown. </p>
  80  *
  81  * @since 9
  82  * @see java.lang.Class#getModule
  83  */
  84 
  85 public final class Module {
  86 
  87     // the layer that contains this module, can be null
  88     private final Layer layer;
  89 
  90     // module name and loader, these fields are read by VM
  91     private final String name;
  92     private final ClassLoader loader;
  93 
  94     // the module descriptor
  95     private final ModuleDescriptor descriptor;
  96 
  97 
  98     /**
  99      * Creates a new named Module. The resulting Module will be defined to the
 100      * VM but will not read any other modules, will not have any exports setup
 101      * and will not be registered in the service catalog.
 102      */
 103     private Module(Layer layer,
 104                    ClassLoader loader,
 105                    ModuleDescriptor descriptor,
 106                    URI uri)
 107     {
 108         this.layer = layer;
 109         this.name = descriptor.name();
 110         this.loader = loader;
 111         this.descriptor = descriptor;
 112 
 113         // define module to VM
 114 
 115         Set<String> packages = descriptor.packages();
 116         int n = packages.size();
 117         String[] array = new String[n];
 118         int i = 0;
 119         for (String pn : packages) {
 120             array[i++] = pn.replace('.', '/');
 121         }
 122         Version version = descriptor.version().orElse(null);
 123         String vs = Objects.toString(version, null);
 124         String loc = Objects.toString(uri, null);
 125 
 126         defineModule0(this, vs, loc, array);
 127     }
 128 
 129 
 130     /**
 131      * Create the unnamed Module for the given ClassLoader.
 132      *
 133      * @see ClassLoader#getUnnamedModule
 134      */
 135     private Module(ClassLoader loader) {
 136         this.layer = null;
 137         this.name = null;
 138         this.loader = loader;
 139         this.descriptor = null;
 140 
 141         // unnamed modules are loose
 142         this.loose = true;
 143     }
 144 
 145 
 146     /**
 147      * Creates a named module but without defining the module to the VM.
 148      *
 149      * @apiNote This constructor is for VM white-box testing.
 150      */
 151     Module(ClassLoader loader, ModuleDescriptor descriptor) {
 152         this.layer = null;
 153         this.name = descriptor.name();
 154         this.loader = loader;
 155         this.descriptor = descriptor;
 156     }
 157 
 158 
 159 
 160     /**
 161      * Returns {@code true} if this module is a named module.
 162      *
 163      * @return {@code true} if this is a named module
 164      *
 165      * @see ClassLoader#getUnnamedModule()
 166      */
 167     public boolean isNamed() {
 168         return name != null;
 169     }
 170 
 171     /**
 172      * Returns the module name or {@code null} if this module is an unnamed
 173      * module.
 174      *
 175      * @return The module name
 176      */
 177     public String getName() {
 178         return name;
 179     }
 180 
 181     /**
 182      * Returns the {@code ClassLoader} for this module.
 183      *
 184      * <p> If there is a security manager then its {@code checkPermission}
 185      * method if first called with a {@code RuntimePermission("getClassLoader")}
 186      * permission to check that the caller is allowed to get access to the
 187      * class loader. </p>
 188      *
 189      * @return The class loader for this module
 190      *
 191      * @throws SecurityException
 192      *         If denied by the security manager
 193      */
 194     public ClassLoader getClassLoader() {
 195         SecurityManager sm = System.getSecurityManager();
 196         if (sm != null) {
 197             sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
 198         }
 199         return loader;
 200     }
 201 
 202     /**
 203      * Returns the module descriptor for this module or {@code null} if this
 204      * module is an unnamed module.
 205      *
 206      * @return The module descriptor for this module
 207      */
 208     public ModuleDescriptor getDescriptor() {
 209         return descriptor;
 210     }
 211 
 212     /**
 213      * Returns the layer that contains this module or {@code null} if this
 214      * module is not in a layer.
 215      *
 216      * A module {@code Layer} contains named modules and therefore this
 217      * method always returns {@code null} when invoked on an unnamed module.
 218      *
 219      * <p> <a href="Proxy.html#dynamicmodule">Dynamic modules</a> are named
 220      * modules that are generated at runtime. A dynamic module may or may
 221      * not be in a module Layer. </p>
 222      *
 223      * @return The layer that contains this module
 224      *
 225      * @see Proxy
 226      */
 227     public Layer getLayer() {
 228         if (isNamed()) {
 229             Layer layer = this.layer;
 230             if (layer != null)
 231                 return layer;
 232 
 233             // special-case java.base as it is created before the boot Layer
 234             if (loader == null && name.equals("java.base")) {
 235                 return SharedSecrets.getJavaLangAccess().getBootLayer();
 236             }
 237         }
 238 
 239         return null;
 240     }
 241 
 242 
 243     // -- readability --
 244 
 245     // true if this module reads all unnamed modules (a.k.a. loose module)
 246     private volatile boolean loose;
 247 
 248     // the modules that this module permanently reads
 249     // (will be final when the modules are defined in reverse topology order)
 250     private volatile Set<Module> reads;
 251 
 252     // additional module (2nd key) that some module (1st key) reflectively reads
 253     private static final WeakPairMap<Module, Module, Boolean> transientReads
 254         = new WeakPairMap<>();
 255 
 256 
 257     /**
 258      * Indicates if this module reads the given module. This method returns
 259      * {@code true} if invoked to test if this module reads itself. It also
 260      * returns {@code true} if invoked on an unnamed module (as unnamed
 261      * modules read all modules).
 262      *
 263      * @param  other
 264      *         The other module
 265      *
 266      * @return {@code true} if this module reads {@code other}
 267      *
 268      * @see #addReads(Module)
 269      */
 270     public boolean canRead(Module other) {
 271         Objects.requireNonNull(other);
 272 
 273         // an unnamed module reads all modules
 274         if (!this.isNamed())
 275             return true;
 276 
 277         // all modules read themselves
 278         if (other == this)
 279             return true;
 280 
 281         // check if this module reads other
 282         if (other.isNamed()) {
 283 
 284             Set<Module> reads = this.reads; // volatile read
 285             if (reads != null && reads.contains(other))
 286                 return true;
 287 
 288         } else {
 289 
 290             // loose modules read all unnamed modules
 291             if (this.loose)
 292                 return true;
 293 
 294         }
 295 
 296         // check if this module reads the other module reflectively
 297         return transientReads.constainsKeyPair(this, other);
 298     }
 299 
 300     /**
 301      * If the caller's module is this module then update this module to read
 302      * the given module.
 303      *
 304      * This method is a no-op if {@code other} is this module (all modules can
 305      * read themselves) or this module is an unnamed module (as unnamed modules
 306      * read all modules).
 307      *
 308      * @param  other
 309      *         The other module
 310      *
 311      * @return this module
 312      *
 313      * @throws IllegalStateException
 314      *         If this is a named module and the caller is not this module
 315      *
 316      * @see #canRead
 317      */
 318     @CallerSensitive
 319     public Module addReads(Module other) {
 320         Objects.requireNonNull(other);
 321         if (this.isNamed()) {
 322             Module caller = Reflection.getCallerClass().getModule();
 323             if (caller != this) {
 324                 throw new IllegalStateException(caller + " != " + this);
 325             }
 326             implAddReads(other, true);
 327         }
 328         return this;
 329     }
 330 
 331     /**
 332      * Updates this module to read another module.
 333      *
 334      * @apiNote This method is for Proxy use and white-box testing.
 335      */
 336     void implAddReads(Module other) {
 337         implAddReads(other, true);
 338     }
 339 
 340     /**
 341      * Makes the given {@code Module} readable to this module without
 342      * notifying the VM.
 343      *
 344      * @apiNote This method is for VM white-box testing.
 345      */
 346     void implAddReadsNoSync(Module other) {
 347         implAddReads(other, false);
 348     }
 349 
 350     /**
 351      * Makes the given {@code Module} readable to this module.
 352      *
 353      * If {@code syncVM} is {@code true} then the VM is notified.
 354      */
 355     private void implAddReads(Module other, boolean syncVM) {
 356 
 357         // nothing to do
 358         if (other == this || !this.isNamed())
 359             return;
 360 
 361         // if the other is null then change this module to be loose.
 362         if (other == null) {
 363             if (syncVM)
 364                 addReads0(this, null);
 365             this.loose = true;
 366             return;
 367         }
 368 
 369         // check if we already read this module
 370         Set<Module> reads = this.reads;
 371         if (reads != null && reads.contains(other))
 372             return;
 373 
 374         // update VM first, just in case it fails
 375         if (syncVM)
 376             addReads0(this, other);
 377 
 378         // add reflective read
 379         transientReads.putIfAbsent(this, other, Boolean.TRUE);
 380     }
 381 
 382 
 383     // -- exports --
 384 
 385     // the packages that are permanently exported
 386     // (will be final when the modules are defined in reverse topology order)
 387     private volatile Map<String, Set<Module>> exports;
 388 
 389     // additional exports added at run-time
 390     // source module (1st key), target module (2nd key), exported packages (value)
 391     private static final WeakPairMap<Module, Module, Set<String>> transientExports =
 392         new WeakPairMap<>();
 393 
 394     // the special Module to mean exported to all modules
 395     private static final Module EVERYONE_MODULE = new Module(null);
 396     private static final Set<Module> EVERYONE = Collections.singleton(EVERYONE_MODULE);
 397 
 398     // the special Module to mean exported to all unnamed modules
 399     private static final Module ALL_UNNAMED_MODULE = new Module(null);
 400 
 401 
 402     /**
 403      * Returns {@code true} if this module exports the given package to at
 404      * least the given module.
 405      *
 406      * <p> This method always return {@code true} when invoked on an unnamed
 407      * module. </p>
 408      *
 409      * <p> This method does not check if the given module reads this module </p>
 410      *
 411      * @param  pn
 412      *         The package name
 413      * @param  other
 414      *         The other module
 415      *
 416      * @return {@code true} if this module exports the package to at least the
 417      *         given module
 418      */
 419     public boolean isExported(String pn, Module other) {
 420         Objects.requireNonNull(pn);
 421         Objects.requireNonNull(other);
 422         return implIsExported(pn, other);
 423     }
 424 
 425     /**
 426      * Returns {@code true} if this module exports the given package
 427      * unconditionally.
 428      *
 429      * <p> This method always return {@code true} when invoked on an unnamed
 430      * module. </p>
 431      *
 432      * <p> This method does not check if the given module reads this module </p>
 433      *
 434      * @param  pn
 435      *         The package name
 436      *
 437      * @return {@code true} if this module exports the package unconditionally
 438      */
 439     public boolean isExported(String pn) {
 440         Objects.requireNonNull(pn);
 441         return implIsExported(pn, EVERYONE_MODULE);
 442     }
 443 
 444     /**
 445      * Returns {@code true} if this module exports the given package to the
 446      * given module. If the other module is {@code EVERYONE_MODULE} then
 447      * this method tests if the package is exported unconditionally.
 448      */
 449     private boolean implIsExported(String pn, Module other) {
 450 
 451         // all packages are exported by unnamed modules
 452         if (!isNamed())
 453             return true;
 454 
 455         // exported via module declaration/descriptor
 456         if (isExportedPermanently(pn, other))
 457             return true;
 458 
 459         // exported via addExports
 460         if (isExportedReflectively(pn, other))
 461             return true;
 462 
 463         // not exported or not exported to other
 464         return false;
 465     }
 466 
 467     /**
 468      * Returns {@code true} if this module permanently exports the given
 469      * package to the given module.
 470      */
 471     private boolean isExportedPermanently(String pn, Module other) {
 472         Map<String, Set<Module>> exports = this.exports;
 473         if (exports != null) {
 474             Set<Module> targets = exports.get(pn);
 475 
 476             if (targets != null) {
 477 
 478                 // exported to all modules
 479                 if (targets.contains(EVERYONE_MODULE))
 480                     return true;
 481 
 482                 if (other != EVERYONE_MODULE) {
 483                     // exported to other
 484                     if (targets.contains(other))
 485                         return true;
 486 
 487                     // other is an unnamed module && exported to all unnamed
 488                     if (!other.isNamed() && targets.contains(ALL_UNNAMED_MODULE))
 489                         return true;
 490                 }
 491 
 492             }
 493         }
 494         return false;
 495     }
 496 
 497     /**
 498      * Returns {@code true} if this module reflectively exports the given
 499      * package package to the given module.
 500      */
 501     private boolean isExportedReflectively(String pn, Module other) {
 502         // exported to all modules
 503         Set<String> exportedToAll = transientExports.get(this, EVERYONE_MODULE);
 504         if (exportedToAll != null && exportedToAll.contains(pn))
 505             return true;
 506 
 507         if (other != EVERYONE_MODULE) {
 508 
 509             // exported to other
 510             Set<String> exportedToOther = transientExports.get(this, other);
 511 
 512             if (exportedToOther != null && exportedToOther.contains(pn))
 513                 return true;
 514 
 515             // other is an unnamed module && exported to all unnamed
 516             if (!other.isNamed()) {
 517                 Set<String> exportedToAllUnnamed = transientExports.get(this, ALL_UNNAMED_MODULE);
 518                 if (exportedToAllUnnamed != null && exportedToAllUnnamed.contains(pn))
 519                     return true;
 520             }
 521         }
 522 
 523         return false;
 524     }
 525 
 526 
 527     /**
 528      * If the caller's module is this module then update this module to export
 529      * package {@code pn} to the given module.
 530      *
 531      * <p> This method has no effect if the package is already exported to the
 532      * given module. If also has no effect if invoked on an unnamed module (as
 533      * unnamed modules export all packages). </p>
 534      *
 535      * @param  pn
 536      *         The package name
 537      * @param  other
 538      *         The module
 539      *
 540      * @return this module
 541      *
 542      * @throws IllegalArgumentException
 543      *         If {@code pn} is {@code null}, or this is a named module and the
 544      *         package {@code pn} is not a package in this module
 545      * @throws IllegalStateException
 546      *         If this is a named module and the caller is not this module
 547      */
 548     @CallerSensitive
 549     public Module addExports(String pn, Module other) {
 550         if (pn == null)
 551             throw new IllegalArgumentException("package is null");
 552         Objects.requireNonNull(other);
 553 
 554         if (isNamed()) {
 555             Module caller = Reflection.getCallerClass().getModule();
 556             if (caller != this) {
 557                 throw new IllegalStateException(caller + " != " + this);
 558             }
 559             implAddExports(pn, other, true);
 560         }
 561 
 562         return this;
 563     }
 564 
 565     /**
 566      * Updates the exports so that package {@code pn} is exported to module
 567      * {@code other} but without notifying the VM.
 568      *
 569      * @apiNote This method is for VM white-box testing.
 570      */
 571     void implAddExportsNoSync(String pn, Module other) {
 572         if (other == null)
 573             other = EVERYONE_MODULE;
 574         implAddExports(pn.replace('/', '.'), other, false);
 575     }
 576 
 577     /**
 578      * Updates the exports so that package {@code pn} is exported to module
 579      * {@code other}.
 580      *
 581      * @apiNote This method is for white-box testing.
 582      */
 583     void implAddExports(String pn, Module other) {
 584         implAddExports(pn, other, true);
 585     }
 586 
 587     /**
 588      * Updates the exports so that package {@code pn} is exported to module
 589      * {@code other}.
 590      *
 591      * If {@code syncVM} is {@code true} then the VM is notified.
 592      */
 593     private void implAddExports(String pn, Module other, boolean syncVM) {
 594         Objects.requireNonNull(other);
 595         Objects.requireNonNull(pn);
 596 
 597         // unnamed modules export all packages
 598         if (!isNamed())
 599             return;
 600 
 601         // nothing to do if already exported to other
 602         if (implIsExported(pn, other))
 603             return;
 604 
 605         // can only export a package in the module
 606         if (!containsPackage(pn)) {
 607             throw new IllegalArgumentException("package " + pn
 608                                                + " not in contents");
 609         }
 610 
 611         // update VM first, just in case it fails
 612         if (syncVM) {
 613             String pkgInternalForm = pn.replace('.', '/');
 614             if (other == EVERYONE_MODULE) {
 615                 addExportsToAll0(this, pkgInternalForm);
 616             } else if (other == ALL_UNNAMED_MODULE) {
 617                 addExportsToAllUnnamed0(this, pkgInternalForm);
 618             } else {
 619                 addExports0(this, pkgInternalForm, other);
 620             }
 621         }
 622 
 623         // add package name to transientExports if absent
 624         transientExports
 625             .computeIfAbsent(this, other, (_this, _other) -> new HashSet<>())
 626             .add(pn);
 627     }
 628 
 629 
 630     // -- services --
 631 
 632     // additional service type (2nd key) that some module (1st key) uses
 633     private static final WeakPairMap<Module, Class<?>, Boolean> transientUses
 634         = new WeakPairMap<>();
 635 
 636     /**
 637      * If the caller's module is this module then update this module to add a
 638      * service dependence on the given service type. This method is intended
 639      * for use by frameworks that invoke {@link java.util.ServiceLoader
 640      * ServiceLoader} on behalf of other modules or where the framework is
 641      * passed a reference to the service type by other code. This method is
 642      * a no-op when invoked on an unnamed module.
 643      *
 644      * <p> This method does not cause {@link
 645      * Configuration#resolveRequiresAndUses resolveRequiresAndUses} to be
 646      * re-run. </p>
 647      *
 648      * @param  st
 649      *         The service type
 650      *
 651      * @return this module
 652      *
 653      * @throws IllegalStateException
 654      *         If this is a named module and the caller is not this module
 655      *
 656      * @see #canUse(Class)
 657      * @see ModuleDescriptor#uses()
 658      */
 659     @CallerSensitive
 660     public Module addUses(Class<?> st) {
 661         Objects.requireNonNull(st);
 662 
 663         if (isNamed()) {
 664 
 665             Module caller = Reflection.getCallerClass().getModule();
 666             if (caller != this) {
 667                 throw new IllegalStateException(caller + " != " + this);
 668             }
 669 
 670             if (!canUse(st)) {
 671                 transientUses.putIfAbsent(this, st, Boolean.TRUE);
 672             }
 673 
 674         }
 675 
 676         return this;
 677     }
 678 
 679     /**
 680      * Indicates if this module has a service dependence on the given service
 681      * type. This method always returns {@code true} when invoked on an unnamed
 682      * module.
 683      *
 684      * @param  st
 685      *         The service type
 686      *
 687      * @return {@code true} if this module uses service type {@code st}
 688      *
 689      * @see #addUses(Class)
 690      */
 691     public boolean canUse(Class<?> st) {
 692         Objects.requireNonNull(st);
 693 
 694         if (!isNamed())
 695             return true;
 696 
 697         if (descriptor.isAutomatic())
 698             return true;
 699 
 700         // uses was declared
 701         if (descriptor.uses().contains(st.getName()))
 702             return true;
 703 
 704         // uses added via addUses
 705         return transientUses.constainsKeyPair(this, st);
 706     }
 707 
 708 
 709 
 710     // -- packages --
 711 
 712     // Additional packages that are added to the module at run-time.
 713     // The field is volatile as it may be replaced at run-time
 714     private volatile Set<String> extraPackages;
 715 
 716     private boolean containsPackage(String pn) {
 717         if (descriptor.packages().contains(pn))
 718             return true;
 719         Set<String> extraPackages = this.extraPackages;
 720         if (extraPackages != null && extraPackages.contains(pn))
 721             return true;
 722         return false;
 723     }
 724 
 725 
 726     /**
 727      * Returns an array of the package names of the packages in this module.
 728      *
 729      * <p> For named modules, the returned array contains an element for each
 730      * package in the module. It may contain elements corresponding to packages
 731      * added to the module, <a href="Proxy.html#dynamicmodule">dynamic modules</a>
 732      * for example, after it was loaded.
 733      *
 734      * <p> For unnamed modules, this method is the equivalent of invoking the
 735      * {@link ClassLoader#getDefinedPackages() getDefinedPackages} method of
 736      * this module's class loader and returning the array of package names. </p>
 737      *
 738      * <p> A package name appears at most once in the returned array. </p>
 739      *
 740      * @apiNote This method returns an array rather than a {@code Set} for
 741      * consistency with other {@code java.lang.reflect} types.
 742      *
 743      * @return an array of the package names of the packages in this module
 744      */
 745     public String[] getPackages() {
 746         if (isNamed()) {
 747 
 748             Set<String> packages = descriptor.packages();
 749             Set<String> extraPackages = this.extraPackages;
 750             if (extraPackages == null) {
 751                 return packages.toArray(new String[0]);
 752             } else {
 753                 return Stream.concat(packages.stream(),
 754                                      extraPackages.stream())
 755                         .toArray(String[]::new);
 756             }
 757 
 758         } else {
 759             // unnamed module
 760             Stream<Package> packages;
 761             if (loader == null) {
 762                 packages = BootLoader.packages();
 763             } else {
 764                 packages = SharedSecrets.getJavaLangAccess().packages(loader);
 765             }
 766             return packages.map(Package::getName).toArray(String[]::new);
 767         }
 768     }
 769 
 770     /**
 771      * Add a package to this module.
 772      *
 773      * @apiNote This method is for Proxy use.
 774      *
 775      * @apiNote This is an expensive operation, not expected to be used often.
 776      * At this time then it does not validate that the package name is a
 777      * valid java identifier.
 778      */
 779     void addPackage(String pn) {
 780         implAddPackage(pn, true);
 781     }
 782 
 783     /**
 784      * Add a package to this module without notifying the VM.
 785      *
 786      * @apiNote This method is VM white-box testing.
 787      */
 788     void implAddPackageNoSync(String pn) {
 789         implAddPackage(pn.replace('/', '.'), false);
 790     }
 791 
 792     /**
 793      * Add a package to this module.
 794      *
 795      * If {@code syncVM} is {@code true} then the VM is notified.
 796      */
 797     private void implAddPackage(String pn, boolean syncVM) {
 798         if (pn.length() == 0)
 799             throw new IllegalArgumentException("<unnamed> package not allowed");
 800 
 801         if (descriptor.packages().contains(pn)) {
 802             // already in module
 803             return;
 804         }
 805 
 806         Set<String> extraPackages = this.extraPackages;
 807         if (extraPackages != null && extraPackages.contains(pn)) {
 808             // already added
 809             return;
 810         }
 811         synchronized (this) {
 812             // recheck under lock
 813             extraPackages = this.extraPackages;
 814             if (extraPackages != null) {
 815                 if (extraPackages.contains(pn)) {
 816                     // already added
 817                     return;
 818                 }
 819 
 820                 // copy the set
 821                 extraPackages = new HashSet<>(extraPackages);
 822                 extraPackages.add(pn);
 823             } else {
 824                 extraPackages = Collections.singleton(pn);
 825             }
 826 
 827             // update VM first, just in case it fails
 828             if (syncVM)
 829                 addPackage0(this, pn.replace('.', '/'));
 830 
 831             // replace with new set
 832             this.extraPackages = extraPackages; // volatile write
 833         }
 834     }
 835 
 836 
 837     // -- creating Module objects --
 838 
 839     /**
 840      * Find the runtime Module corresponding to the given ReadDependence
 841      * in the given parent Layer (or its parents).
 842      */
 843     private static Module find(ResolvedModule resolvedModule, Layer layer) {
 844         Configuration cf = resolvedModule.configuration();
 845         String dn = resolvedModule.name();
 846 
 847         Module m = null;
 848         while (layer != null) {
 849             if (layer.configuration() == cf) {
 850                 Optional<Module> om = layer.findModule(dn);
 851                 m = om.get();
 852                 assert m.getLayer() == layer;
 853                 break;
 854             }
 855             layer = layer.parent().orElse(null);
 856         }
 857         return m;
 858     }
 859 
 860     /**
 861      * Defines each of the module in the given configuration to the runtime.
 862      *
 863      * @return a map of module name to runtime {@code Module}
 864      *
 865      * @throws IllegalArgumentException
 866      *         If defining any of the modules to the VM fails
 867      */
 868     static Map<String, Module> defineModules(Configuration cf,
 869                                              Function<String, ClassLoader> clf,
 870                                              Layer layer)
 871     {
 872         Map<String, Module> modules = new HashMap<>();
 873         Map<String, ClassLoader> loaders = new HashMap<>();
 874 
 875         // define each module in the configuration to the VM
 876         for (ResolvedModule resolvedModule : cf.modules()) {
 877             ModuleReference mref = resolvedModule.reference();
 878             ModuleDescriptor descriptor = mref.descriptor();
 879             String name = descriptor.name();
 880             ClassLoader loader = clf.apply(name);
 881             URI uri = mref.location().orElse(null);
 882 
 883             Module m;
 884             if (loader == null && name.equals("java.base")) {
 885                 m = Object.class.getModule();
 886             } else {
 887                 m = new Module(layer, loader, descriptor, uri);
 888             }
 889 
 890             modules.put(name, m);
 891             loaders.put(name, loader);
 892         }
 893 
 894         // setup readability and exports
 895         for (ResolvedModule resolvedModule : cf.modules()) {
 896             ModuleReference mref = resolvedModule.reference();
 897             ModuleDescriptor descriptor = mref.descriptor();
 898 
 899             String mn = descriptor.name();
 900             Module m = modules.get(mn);
 901             assert m != null;
 902 
 903             // reads
 904             Set<Module> reads = new HashSet<>();
 905             for (ResolvedModule d : resolvedModule.reads()) {
 906                 Module m2;
 907                 if (d.configuration() == cf) {
 908                     String dn = d.reference().descriptor().name();
 909                     m2 = modules.get(dn);
 910                     assert m2 != null;
 911                 } else {
 912                     m2 = find(d, layer.parent().orElse(null));
 913                 }
 914 
 915                 reads.add(m2);
 916 
 917                 // update VM view
 918                 addReads0(m, m2);
 919             }
 920             m.reads = reads;
 921 
 922             // automatic modules reads all unnamed modules
 923             if (descriptor.isAutomatic()) {
 924                 m.implAddReads(null, true);
 925             }
 926 
 927             // exports
 928             Map<String, Set<Module>> exports = new HashMap<>();
 929             for (Exports export : descriptor.exports()) {
 930                 String source = export.source();
 931                 String sourceInternalForm = source.replace('.', '/');
 932 
 933                 if (export.isQualified()) {
 934 
 935                     // qualified export
 936                     Set<Module> targets = new HashSet<>();
 937                     for (String target : export.targets()) {
 938                         // only export to modules that are in this configuration
 939                         Module m2 = modules.get(target);
 940                         if (m2 != null) {
 941                             targets.add(m2);
 942                             addExports0(m, sourceInternalForm, m2);
 943                         }
 944                     }
 945                     if (!targets.isEmpty()) {
 946                         exports.put(source, targets);
 947                     }
 948 
 949                 } else {
 950 
 951                     // unqualified export
 952                     exports.put(source, EVERYONE);
 953                     addExportsToAll0(m, sourceInternalForm);
 954                 }
 955             }
 956             m.exports = exports;
 957         }
 958 
 959         // register the modules in the service catalog if they provide services
 960         for (ResolvedModule resolvedModule : cf.modules()) {
 961             ModuleReference mref = resolvedModule.reference();
 962             ModuleDescriptor descriptor = mref.descriptor();
 963             Map<String, Provides> services = descriptor.provides();
 964             if (!services.isEmpty()) {
 965                 String name = descriptor.name();
 966                 Module m = modules.get(name);
 967                 ClassLoader loader = loaders.get(name);
 968                 ServicesCatalog catalog;
 969                 if (loader == null) {
 970                     catalog = BootLoader.getServicesCatalog();
 971                 } else {
 972                     catalog = SharedSecrets.getJavaLangAccess()
 973                                            .createOrGetServicesCatalog(loader);
 974                 }
 975                 catalog.register(m);
 976             }
 977         }
 978 
 979         return modules;
 980     }
 981 
 982 
 983     // -- misc --
 984 
 985 
 986     /**
 987      * Returns an input stream for reading a resource in this module. Returns
 988      * {@code null} if the resource is not in this module or access to the
 989      * resource is denied by the security manager.
 990      * The {@code name} is a {@code '/'}-separated path name that identifies
 991      * the resource.
 992      *
 993      * <p> If this module is an unnamed module, and the {@code ClassLoader} for
 994      * this module is not {@code null}, then this method is equivalent to
 995      * invoking the {@link ClassLoader#getResourceAsStream(String)
 996      * getResourceAsStream} method on the class loader for this module.
 997      *
 998      * @param  name
 999      *         The resource name
1000      *
1001      * @return An input stream for reading the resource or {@code null}
1002      *
1003      * @throws IOException
1004      *         If an I/O error occurs
1005      *
1006      * @see java.lang.module.ModuleReader#open(String)
1007      */
1008     public InputStream getResourceAsStream(String name) throws IOException {
1009         Objects.requireNonNull(name);
1010 
1011         URL url = null;
1012 
1013         if (isNamed()) {
1014             String mn = this.name;
1015 
1016             // special-case built-in class loaders to avoid URL connection
1017             if (loader == null) {
1018                 return BootLoader.findResourceAsStream(mn, name);
1019             } else if (loader instanceof BuiltinClassLoader) {
1020                 return ((BuiltinClassLoader) loader).findResourceAsStream(mn, name);
1021             }
1022 
1023             // use SharedSecrets to invoke protected method
1024             url = SharedSecrets.getJavaLangAccess().findResource(loader, mn, name);
1025 
1026         } else {
1027 
1028             // unnamed module
1029             if (loader == null) {
1030                 url = BootLoader.findResource(name);
1031             } else {
1032                 return loader.getResourceAsStream(name);
1033             }
1034 
1035         }
1036 
1037         // fallthrough to URL case
1038         if (url != null) {
1039             try {
1040                 return url.openStream();
1041             } catch (SecurityException e) { }
1042         }
1043 
1044         return null;
1045     }
1046 
1047     /**
1048      * Returns the string representation of this module. For a named module,
1049      * the representation is the string {@code "module"}, followed by a space,
1050      * and then the module name. For an unnamed module, the representation is
1051      * the string {@code "unnamed module"}, followed by a space, and then an
1052      * implementation specific identifier for the unnamed module.
1053      *
1054      * @return The string representation of this module
1055      */
1056     @Override
1057     public String toString() {
1058         if (isNamed()) {
1059             return "module " + name;
1060         } else {
1061             String id = Integer.toHexString(System.identityHashCode(this));
1062             return "unnamed module @" + id;
1063         }
1064     }
1065 
1066 
1067     // -- native methods --
1068 
1069     // JVM_DefineModule
1070     private static native void defineModule0(Module module,
1071                                              String version,
1072                                              String location,
1073                                              String[] pns);
1074 
1075     // JVM_AddReadsModule
1076     private static native void addReads0(Module from, Module to);
1077 
1078     // JVM_AddModuleExports
1079     private static native void addExports0(Module from, String pn, Module to);
1080 
1081     // JVM_AddModuleExportsToAll
1082     private static native void addExportsToAll0(Module from, String pn);
1083 
1084     // JVM_AddModuleExportsToAllUnnamed
1085     private static native void addExportsToAllUnnamed0(Module from, String pn);
1086 
1087     // JVM_AddModulePackage
1088     private static native void addPackage0(Module m, String pn);
1089 
1090     /**
1091      * Register shared secret to provide access to package-private methods
1092      */
1093     static {
1094         SharedSecrets.setJavaLangReflectModuleAccess(
1095             new JavaLangReflectModuleAccess() {
1096                 @Override
1097                 public Module defineUnnamedModule(ClassLoader loader) {
1098                     return new Module(loader);
1099                 }
1100                 @Override
1101                 public Module defineModule(ClassLoader loader,
1102                                            ModuleDescriptor descriptor,
1103                                            URI uri) {
1104                    return new Module(null, loader, descriptor, uri);
1105                 }
1106                 @Override
1107                 public void addReads(Module m1, Module m2) {
1108                     m1.implAddReads(m2, true);
1109                 }
1110                 @Override
1111                 public void addExports(Module m, String pn, Module other) {
1112                     m.implAddExports(pn, Objects.requireNonNull(other), true);
1113                 }
1114                 @Override
1115                 public void addExportsToAll(Module m, String pn) {
1116                     m.implAddExports(pn, Module.EVERYONE_MODULE, true);
1117                 }
1118                 @Override
1119                 public void addExportsToAllUnnamed(Module m, String pn) {
1120                     m.implAddExports(pn, Module.ALL_UNNAMED_MODULE, true);
1121                 }
1122                 @Override
1123                 public void addPackage(Module m, String pn) {
1124                     m.implAddPackage(pn, true);
1125                 }
1126             });
1127     }
1128 }