< prev index next >

src/java.base/share/classes/java/lang/reflect/Layer.java

Print this page




  49 import jdk.internal.loader.LoaderPool;
  50 import jdk.internal.misc.SharedSecrets;
  51 import jdk.internal.module.Modules;
  52 import jdk.internal.module.ServicesCatalog;
  53 import sun.security.util.SecurityConstants;
  54 
  55 
  56 /**
  57  * A layer of modules in the Java virtual machine.
  58  *
  59  * <p> A layer is created from a graph of modules in a {@link Configuration}
  60  * and a function that maps each module to a {@link ClassLoader}.
  61  * Creating a layer informs the Java virtual machine about the classes that
  62  * may be loaded from the modules so that the Java virtual machine knows which
  63  * module that each class is a member of. </p>
  64  *
  65  * <p> Creating a layer creates a {@link Module} object for each {@link
  66  * ResolvedModule} in the configuration. For each resolved module that is
  67  * {@link ResolvedModule#reads() read}, the {@code Module} {@link
  68  * Module#canRead reads} the corresponding run-time {@code Module}, which may
  69  * be in the same layer or a {@link #parents() parent} layer. The {@code Module}
  70  * {@link Module#isExported(String) exports} and {@link Module#isOpen(String)
  71  * opens} the packages described by its {@link ModuleDescriptor}. </p>
  72  *
  73  * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
  74  * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
  75  * provide convenient ways to create a {@code Layer} where all modules are
  76  * mapped to a single class loader or where each module is mapped to its own
  77  * class loader. The {@link #defineModules defineModules} method is for more
  78  * advanced cases where modules are mapped to custom class loaders by means of
  79  * a function specified to the method. Each of these methods has an instance
  80  * and static variant. The instance methods create a layer with the receiver
  81  * as the parent layer. The static methods are for more advanced cases where
  82  * there can be more than one parent layer or where a {@link Layer.Controller
  83  * Controller} is needed to control modules in the layer. </p>
  84  *
  85  * <p> A Java virtual machine has at least one non-empty layer, the {@link
  86  * #boot() boot} layer, that is created when the Java virtual machine is
  87  * started. The boot layer contains module {@code java.base} and is the only
  88  * layer in the Java virtual machine with a module named "{@code java.base}".
  89  * The modules in the boot layer are mapped to the bootstrap class loader and
  90  * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
  91  * built-in</a> into the Java virtual machine. The boot layer will often be
  92  * the {@link #parents() parent} when creating additional layers. </p>
  93  *






















  94  * <p> As when creating a {@code Configuration},
  95  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive special
  96  * treatment when creating a layer. An automatic module is created in the
  97  * Java virtual machine as a {@code Module} that reads every unnamed {@code
  98  * Module} in the Java virtual machine. </p>
  99  *
 100  * <p> Unless otherwise specified, passing a {@code null} argument to a method
 101  * in this class causes a {@link NullPointerException NullPointerException} to
 102  * be thrown. </p>
 103  *
 104  * <h3> Example usage: </h3>
 105  *
 106  * <p> This example creates a configuration by resolving a module named
 107  * "{@code myapp}" with the configuration for the boot layer as the parent. It
 108  * then creates a new layer with the modules in this configuration. All modules
 109  * are defined to the same class loader. </p>
 110  *
 111  * <pre>{@code
 112  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
 113  *


 176      * @since 9
 177      * @spec JPMS
 178      */
 179     public static final class Controller {
 180         private final Layer layer;
 181 
 182         Controller(Layer layer) {
 183             this.layer = layer;
 184         }
 185 
 186         /**
 187          * Returns the layer that this object controls.
 188          *
 189          * @return the layer
 190          */
 191         public Layer layer() {
 192             return layer;
 193         }
 194 
 195         private void ensureInLayer(Module source) {
 196             if (!layer.modules().contains(source))
 197                 throw new IllegalArgumentException(source + " not in layer");
 198         }
 199 
 200 
 201         /**
 202          * Updates module {@code source} in the layer to read module
 203          * {@code target}. This method is a no-op if {@code source} already
 204          * reads {@code target}.
 205          *
 206          * @implNote <em>Read edges</em> added by this method are <em>weak</em>
 207          * and do not prevent {@code target} from being GC'ed when {@code source}
 208          * is strongly reachable.
 209          *
 210          * @param  source
 211          *         The source module
 212          * @param  target
 213          *         The target module to read
 214          *
 215          * @return This controller
 216          *
 217          * @throws IllegalArgumentException
 218          *         If {@code source} is not in the layer
 219          *
 220          * @see Module#addReads
 221          */
 222         public Controller addReads(Module source, Module target) {
 223             Objects.requireNonNull(source);
 224             Objects.requireNonNull(target);
 225             ensureInLayer(source);

 226             Modules.addReads(source, target);
 227             return this;
 228         }
 229 
 230         /**
 231          * Updates module {@code source} in the layer to open a package to
 232          * module {@code target}. This method is a no-op if {@code source}
 233          * already opens the package to at least {@code target}.
 234          *
 235          * @param  source
 236          *         The source module
 237          * @param  pn
 238          *         The package name
 239          * @param  target
 240          *         The target module to read
 241          *
 242          * @return This controller
 243          *
 244          * @throws IllegalArgumentException
 245          *         If {@code source} is not in the layer or the package is not
 246          *         in the source module
 247          *
 248          * @see Module#addOpens
 249          */
 250         public Controller addOpens(Module source, String pn, Module target) {
 251             Objects.requireNonNull(source);
 252             Objects.requireNonNull(target);
 253             ensureInLayer(source);


 254             Modules.addOpens(source, pn, target);
 255             return this;
 256         }
 257     }
 258 
 259 
 260     /**
 261      * Creates a new layer, with this layer as its parent, by defining the
 262      * modules in the given {@code Configuration} to the Java virtual machine.
 263      * This method creates one class loader and defines all modules to that
 264      * class loader. The {@link ClassLoader#getParent() parent} of each class
 265      * loader is the given parent class loader. This method works exactly as
 266      * specified by the static {@link
 267      * #defineModulesWithOneLoader(Configuration,List,ClassLoader)
 268      * defineModulesWithOneLoader} method when invoked with this layer as the
 269      * parent. In other words, if this layer is {@code thisLayer} then this
 270      * method is equivalent to invoking:
 271      * <pre> {@code
 272      *     Layer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer();
 273      * }</pre>


 391      * loader delegates to the class loader of the module, throwing {@code
 392      * ClassNotFoundException} if not found by that class loader.
 393      * When {@code loadClass} is invoked to load classes that do not map to a
 394      * module then it delegates to the parent class loader. </p>
 395      *
 396      * <p> Attempting to create a layer with all modules defined to the same
 397      * class loader can fail for the following reasons:
 398      *
 399      * <ul>
 400      *
 401      *     <li><p> <em>Overlapping packages</em>: Two or more modules in the
 402      *     configuration have the same package. </p></li>
 403      *
 404      *     <li><p> <em>Split delegation</em>: The resulting class loader would
 405      *     need to delegate to more than one class loader in order to load types
 406      *     in a specific package. </p></li>
 407      *
 408      * </ul>
 409      *
 410      * <p> In addition, a layer cannot be created if the configuration contains
 411      * a module named "{@code java.base}" or a module with a package name
 412      * starting with "{@code java.}". </p>
 413      *
 414      * <p> If there is a security manager then the class loader created by
 415      * this method will load classes and resources with privileges that are
 416      * restricted by the calling context of this method. </p>
 417      *
 418      * @param  cf
 419      *         The configuration for the layer
 420      * @param  parentLayers
 421      *         The list parent layers in search order
 422      * @param  parentLoader
 423      *         The parent class loader for the class loader created by this
 424      *         method; may be {@code null} for the bootstrap class loader
 425      *
 426      * @return A controller that controls the newly created layer
 427      *
 428      * @throws IllegalArgumentException
 429      *         If the parent configurations do not match the configuration of
 430      *         the parent layers, including order
 431      * @throws LayerInstantiationException
 432      *         If all modules cannot be defined to the same class loader for any
 433      *         of the reasons listed above
 434      * @throws SecurityException
 435      *         If {@code RuntimePermission("createClassLoader")} or
 436      *         {@code RuntimePermission("getClassLoader")} is denied by
 437      *         the security manager
 438      *
 439      * @see #findLoader
 440      */
 441     public static Controller defineModulesWithOneLoader(Configuration cf,


 468      * <p> The class loaders created by this method implement <em>direct
 469      * delegation</em> when loading types from modules. When {@link
 470      * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
 471      * load a class then it uses the package name of the class to map it to a
 472      * module. The package may be in the module defined to the class loader.
 473      * The package may be exported by another module in this layer to the
 474      * module defined to the class loader. It may be in a package exported by a
 475      * module in a parent layer. The class loader delegates to the class loader
 476      * of the module, throwing {@code ClassNotFoundException} if not found by
 477      * that class loader.
 478      * When {@code loadClass} is invoked to load classes that do not map to a
 479      * module then it delegates to the parent class loader. </p>
 480      *
 481      * <p> If there is a security manager then the class loaders created by
 482      * this method will load classes and resources with privileges that are
 483      * restricted by the calling context of this method. </p>
 484      *
 485      * @param  cf
 486      *         The configuration for the layer
 487      * @param  parentLayers
 488      *         The list parent layers in search order
 489      * @param  parentLoader
 490      *         The parent class loader for each of the class loaders created by
 491      *         this method; may be {@code null} for the bootstrap class loader
 492      *
 493      * @return A controller that controls the newly created layer
 494      *
 495      * @throws IllegalArgumentException
 496      *         If the parent configurations do not match the configuration of
 497      *         the parent layers, including order
 498      * @throws LayerInstantiationException
 499      *         If the layer cannot be created because the configuration contains
 500      *         a module named "{@code java.base}" or a module with a package
 501      *         name starting with "{@code java.}"


 502      * @throws SecurityException
 503      *         If {@code RuntimePermission("createClassLoader")} or
 504      *         {@code RuntimePermission("getClassLoader")} is denied by
 505      *         the security manager
 506      *
 507      * @see #findLoader
 508      */
 509     public static Controller defineModulesWithManyLoaders(Configuration cf,
 510                                                           List<Layer> parentLayers,
 511                                                           ClassLoader parentLoader)
 512     {
 513         List<Layer> parents = new ArrayList<>(parentLayers);
 514         checkConfiguration(cf, parents);
 515 
 516         checkCreateClassLoaderPermission();
 517         checkGetClassLoaderPermission();
 518 
 519         LoaderPool pool = new LoaderPool(cf, parents, parentLoader);
 520         try {
 521             Layer layer = new Layer(cf, parents, pool::loaderFor);


 541      * ready to load from these modules before there are any attempts to load
 542      * classes or resources. </p>
 543      *
 544      * <p> Creating a {@code Layer} can fail for the following reasons: </p>
 545      *
 546      * <ul>
 547      *
 548      *     <li><p> Two or more modules with the same package are mapped to the
 549      *     same class loader. </p></li>
 550      *
 551      *     <li><p> A module is mapped to a class loader that already has a
 552      *     module of the same name defined to it. </p></li>
 553      *
 554      *     <li><p> A module is mapped to a class loader that has already
 555      *     defined types in any of the packages in the module. </p></li>
 556      *
 557      * </ul>
 558      *
 559      * <p> In addition, a layer cannot be created if the configuration contains
 560      * a module named "{@code java.base}", a configuration contains a module
 561      * with a package name starting with "{@code java.}" is mapped to a class
 562      * loader other than the {@link ClassLoader#getPlatformClassLoader()
 563      * platform class loader}, or the function to map a module name to a class
 564      * loader returns {@code null}. </p>

 565      *
 566      * <p> If the function to map a module name to class loader throws an error
 567      * or runtime exception then it is propagated to the caller of this method.
 568      * </p>
 569      *
 570      * @apiNote It is implementation specific as to whether creating a Layer
 571      * with this method is an atomic operation or not. Consequentially it is
 572      * possible for this method to fail with some modules, but not all, defined
 573      * to the Java virtual machine.
 574      *
 575      * @param  cf
 576      *         The configuration for the layer
 577      * @param  parentLayers
 578      *         The list parent layers in search order
 579      * @param  clf
 580      *         The function to map a module name to a class loader
 581      *
 582      * @return A controller that controls the newly created layer
 583      *
 584      * @throws IllegalArgumentException
 585      *         If the parent configurations do not match the configuration of
 586      *         the parent layers, including order
 587      * @throws LayerInstantiationException
 588      *         If creating the layer fails for any of the reasons listed above
 589      * @throws SecurityException
 590      *         If {@code RuntimePermission("getClassLoader")} is denied by
 591      *         the security manager
 592      */
 593     public static Controller defineModules(Configuration cf,
 594                                            List<Layer> parentLayers,
 595                                            Function<String, ClassLoader> clf)
 596     {
 597         List<Layer> parents = new ArrayList<>(parentLayers);
 598         checkConfiguration(cf, parents);


 737                 Layer parent = layer.parents.get(i);
 738                 if (!visited.contains(parent)) {
 739                     visited.add(parent);
 740                     stack.push(parent);
 741                 }
 742             }
 743         }
 744 
 745         this.allLayers = allLayers = Collections.unmodifiableList(allLayers);
 746         return allLayers.stream();
 747     }
 748 
 749     private volatile List<Layer> allLayers;
 750 
 751     /**
 752      * Returns the set of the modules in this layer.
 753      *
 754      * @return A possibly-empty unmodifiable set of the modules in this layer
 755      */
 756     public Set<Module> modules() {
 757         return Collections.unmodifiableSet(
 758                 nameToModule.values().stream().collect(Collectors.toSet()));


 759     }




 760 
 761 
 762     /**
 763      * Returns the module with the given name in this layer, or if not in this
 764      * layer, the {@linkplain #parents parent} layers. Finding a module in
 765      * parent layers is equivalent to invoking {@code findModule} on each
 766      * parent, in search order, until the module is found or all parents have
 767      * been searched. In a <em>tree of layers</em>  then this is equivalent to
 768      * a depth-first search.
 769      *
 770      * @param  name
 771      *         The name of the module to find
 772      *
 773      * @return The module with the given name or an empty {@code Optional}
 774      *         if there isn't a module with this name in this layer or any
 775      *         parent layer
 776      */
 777     public Optional<Module> findModule(String name) {
 778         Objects.requireNonNull(name);


 779         Module m = nameToModule.get(name);
 780         if (m != null)
 781             return Optional.of(m);
 782 
 783         return layers()
 784                 .skip(1)  // skip this layer
 785                 .map(l -> l.nameToModule)
 786                 .filter(map -> map.containsKey(name))
 787                 .map(map -> map.get(name))
 788                 .findAny();
 789     }
 790 
 791 
 792     /**
 793      * Returns the {@code ClassLoader} for the module with the given name. If
 794      * a module of the given name is not in this layer then the {@link #parents
 795      * parent} layers are searched in the manner specified by {@link
 796      * #findModule(String) findModule}.
 797      *
 798      * <p> If there is a security manager then its {@code checkPermission}




  49 import jdk.internal.loader.LoaderPool;
  50 import jdk.internal.misc.SharedSecrets;
  51 import jdk.internal.module.Modules;
  52 import jdk.internal.module.ServicesCatalog;
  53 import sun.security.util.SecurityConstants;
  54 
  55 
  56 /**
  57  * A layer of modules in the Java virtual machine.
  58  *
  59  * <p> A layer is created from a graph of modules in a {@link Configuration}
  60  * and a function that maps each module to a {@link ClassLoader}.
  61  * Creating a layer informs the Java virtual machine about the classes that
  62  * may be loaded from the modules so that the Java virtual machine knows which
  63  * module that each class is a member of. </p>
  64  *
  65  * <p> Creating a layer creates a {@link Module} object for each {@link
  66  * ResolvedModule} in the configuration. For each resolved module that is
  67  * {@link ResolvedModule#reads() read}, the {@code Module} {@link
  68  * Module#canRead reads} the corresponding run-time {@code Module}, which may
  69  * be in the same layer or a {@link #parents() parent} layer. </p>


  70  *
  71  * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
  72  * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
  73  * provide convenient ways to create a {@code Layer} where all modules are
  74  * mapped to a single class loader or where each module is mapped to its own
  75  * class loader. The {@link #defineModules defineModules} method is for more
  76  * advanced cases where modules are mapped to custom class loaders by means of
  77  * a function specified to the method. Each of these methods has an instance
  78  * and static variant. The instance methods create a layer with the receiver
  79  * as the parent layer. The static methods are for more advanced cases where
  80  * there can be more than one parent layer or where a {@link Layer.Controller
  81  * Controller} is needed to control modules in the layer. </p>
  82  *
  83  * <p> A Java virtual machine has at least one non-empty layer, the {@link
  84  * #boot() boot} layer, that is created when the Java virtual machine is
  85  * started. The boot layer contains module {@code java.base} and is the only
  86  * layer in the Java virtual machine with a module named "{@code java.base}".
  87  * The modules in the boot layer are mapped to the bootstrap class loader and
  88  * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
  89  * built-in</a> into the Java virtual machine. The boot layer will often be
  90  * the {@link #parents() parent} when creating additional layers. </p>
  91  *
  92  * <p> Each {@code Module} in a layer is created so that it {@link
  93  * Module#isExported(String) exports} and {@link Module#isOpen(String) opens}
  94  * the packages described by its {@link ModuleDescriptor}. Qualified exports
  95  * (where a package is exported to a set of target modules rather than all
  96  * modules) are reified when creating the layer as follows: </p>
  97  * <ul>
  98  *     <li> If module {@code X} exports a package to {@code Y}, and if the
  99  *     runtime {@code Module} {@code X} reads {@code Module} {@code Y}, then
 100  *     the package is exported to {@code Module} {@code Y} (which may be in
 101  *     the same layer as {@code X} or a parent layer). </li>
 102  *
 103  *     <li> If module {@code X} exports a package to {@code Y}, and if the
 104  *     runtime {@code Module} {@code X} does not read {@code Y} then target
 105  *     {@code Y} is located as if by invoking {@link #findModule(String)
 106  *     findModule} to find the module in the layer or its parent layers. If
 107  *     {@code Y} is found then the package is exported to the instance of
 108  *     {@code Y} that was found. If {@code Y} is not found then the qualified
 109  *     export is ignored. </li>
 110  * </ul>
 111  *
 112  * <p> Qualified opens are handled in same way as qualified exports. </p>
 113  *
 114  * <p> As when creating a {@code Configuration},
 115  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive special
 116  * treatment when creating a layer. An automatic module is created in the
 117  * Java virtual machine as a {@code Module} that reads every unnamed {@code
 118  * Module} in the Java virtual machine. </p>
 119  *
 120  * <p> Unless otherwise specified, passing a {@code null} argument to a method
 121  * in this class causes a {@link NullPointerException NullPointerException} to
 122  * be thrown. </p>
 123  *
 124  * <h3> Example usage: </h3>
 125  *
 126  * <p> This example creates a configuration by resolving a module named
 127  * "{@code myapp}" with the configuration for the boot layer as the parent. It
 128  * then creates a new layer with the modules in this configuration. All modules
 129  * are defined to the same class loader. </p>
 130  *
 131  * <pre>{@code
 132  *     ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3);
 133  *


 196      * @since 9
 197      * @spec JPMS
 198      */
 199     public static final class Controller {
 200         private final Layer layer;
 201 
 202         Controller(Layer layer) {
 203             this.layer = layer;
 204         }
 205 
 206         /**
 207          * Returns the layer that this object controls.
 208          *
 209          * @return the layer
 210          */
 211         public Layer layer() {
 212             return layer;
 213         }
 214 
 215         private void ensureInLayer(Module source) {
 216             if (source.getLayer() != layer)
 217                 throw new IllegalArgumentException(source + " not in layer");
 218         }
 219 
 220 
 221         /**
 222          * Updates module {@code source} in the layer to read module
 223          * {@code target}. This method is a no-op if {@code source} already
 224          * reads {@code target}.
 225          *
 226          * @implNote <em>Read edges</em> added by this method are <em>weak</em>
 227          * and do not prevent {@code target} from being GC'ed when {@code source}
 228          * is strongly reachable.
 229          *
 230          * @param  source
 231          *         The source module
 232          * @param  target
 233          *         The target module to read
 234          *
 235          * @return This controller
 236          *
 237          * @throws IllegalArgumentException
 238          *         If {@code source} is not in the layer
 239          *
 240          * @see Module#addReads
 241          */
 242         public Controller addReads(Module source, Module target) {


 243             ensureInLayer(source);
 244             Objects.requireNonNull(target);
 245             Modules.addReads(source, target);
 246             return this;
 247         }
 248 
 249         /**
 250          * Updates module {@code source} in the layer to open a package to
 251          * module {@code target}. This method is a no-op if {@code source}
 252          * already opens the package to at least {@code target}.
 253          *
 254          * @param  source
 255          *         The source module
 256          * @param  pn
 257          *         The package name
 258          * @param  target
 259          *         The target module to read
 260          *
 261          * @return This controller
 262          *
 263          * @throws IllegalArgumentException
 264          *         If {@code source} is not in the layer or the package is not
 265          *         in the source module
 266          *
 267          * @see Module#addOpens
 268          */
 269         public Controller addOpens(Module source, String pn, Module target) {


 270             ensureInLayer(source);
 271             Objects.requireNonNull(pn);
 272             Objects.requireNonNull(target);
 273             Modules.addOpens(source, pn, target);
 274             return this;
 275         }
 276     }
 277 
 278 
 279     /**
 280      * Creates a new layer, with this layer as its parent, by defining the
 281      * modules in the given {@code Configuration} to the Java virtual machine.
 282      * This method creates one class loader and defines all modules to that
 283      * class loader. The {@link ClassLoader#getParent() parent} of each class
 284      * loader is the given parent class loader. This method works exactly as
 285      * specified by the static {@link
 286      * #defineModulesWithOneLoader(Configuration,List,ClassLoader)
 287      * defineModulesWithOneLoader} method when invoked with this layer as the
 288      * parent. In other words, if this layer is {@code thisLayer} then this
 289      * method is equivalent to invoking:
 290      * <pre> {@code
 291      *     Layer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer();
 292      * }</pre>


 410      * loader delegates to the class loader of the module, throwing {@code
 411      * ClassNotFoundException} if not found by that class loader.
 412      * When {@code loadClass} is invoked to load classes that do not map to a
 413      * module then it delegates to the parent class loader. </p>
 414      *
 415      * <p> Attempting to create a layer with all modules defined to the same
 416      * class loader can fail for the following reasons:
 417      *
 418      * <ul>
 419      *
 420      *     <li><p> <em>Overlapping packages</em>: Two or more modules in the
 421      *     configuration have the same package. </p></li>
 422      *
 423      *     <li><p> <em>Split delegation</em>: The resulting class loader would
 424      *     need to delegate to more than one class loader in order to load types
 425      *     in a specific package. </p></li>
 426      *
 427      * </ul>
 428      *
 429      * <p> In addition, a layer cannot be created if the configuration contains
 430      * a module named "{@code java.base}", or a module contains a package named
 431      * "{@code java}" or a package with a name starting with "{@code java.}". </p>
 432      *
 433      * <p> If there is a security manager then the class loader created by
 434      * this method will load classes and resources with privileges that are
 435      * restricted by the calling context of this method. </p>
 436      *
 437      * @param  cf
 438      *         The configuration for the layer
 439      * @param  parentLayers
 440      *         The list of parent layers in search order
 441      * @param  parentLoader
 442      *         The parent class loader for the class loader created by this
 443      *         method; may be {@code null} for the bootstrap class loader
 444      *
 445      * @return A controller that controls the newly created layer
 446      *
 447      * @throws IllegalArgumentException
 448      *         If the parent configurations do not match the configuration of
 449      *         the parent layers, including order
 450      * @throws LayerInstantiationException
 451      *         If all modules cannot be defined to the same class loader for any
 452      *         of the reasons listed above
 453      * @throws SecurityException
 454      *         If {@code RuntimePermission("createClassLoader")} or
 455      *         {@code RuntimePermission("getClassLoader")} is denied by
 456      *         the security manager
 457      *
 458      * @see #findLoader
 459      */
 460     public static Controller defineModulesWithOneLoader(Configuration cf,


 487      * <p> The class loaders created by this method implement <em>direct
 488      * delegation</em> when loading types from modules. When {@link
 489      * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to
 490      * load a class then it uses the package name of the class to map it to a
 491      * module. The package may be in the module defined to the class loader.
 492      * The package may be exported by another module in this layer to the
 493      * module defined to the class loader. It may be in a package exported by a
 494      * module in a parent layer. The class loader delegates to the class loader
 495      * of the module, throwing {@code ClassNotFoundException} if not found by
 496      * that class loader.
 497      * When {@code loadClass} is invoked to load classes that do not map to a
 498      * module then it delegates to the parent class loader. </p>
 499      *
 500      * <p> If there is a security manager then the class loaders created by
 501      * this method will load classes and resources with privileges that are
 502      * restricted by the calling context of this method. </p>
 503      *
 504      * @param  cf
 505      *         The configuration for the layer
 506      * @param  parentLayers
 507      *         The list of parent layers in search order
 508      * @param  parentLoader
 509      *         The parent class loader for each of the class loaders created by
 510      *         this method; may be {@code null} for the bootstrap class loader
 511      *
 512      * @return A controller that controls the newly created layer
 513      *
 514      * @throws IllegalArgumentException
 515      *         If the parent configurations do not match the configuration of
 516      *         the parent layers, including order
 517      * @throws LayerInstantiationException
 518      *         If the layer cannot be created because the configuration contains
 519      *         a module named "{@code java.base}" or a module contains a package
 520      *         named "{@code java}" or a package with a name starting with
 521      *         "{@code java.}"
 522      *
 523      * @throws SecurityException
 524      *         If {@code RuntimePermission("createClassLoader")} or
 525      *         {@code RuntimePermission("getClassLoader")} is denied by
 526      *         the security manager
 527      *
 528      * @see #findLoader
 529      */
 530     public static Controller defineModulesWithManyLoaders(Configuration cf,
 531                                                           List<Layer> parentLayers,
 532                                                           ClassLoader parentLoader)
 533     {
 534         List<Layer> parents = new ArrayList<>(parentLayers);
 535         checkConfiguration(cf, parents);
 536 
 537         checkCreateClassLoaderPermission();
 538         checkGetClassLoaderPermission();
 539 
 540         LoaderPool pool = new LoaderPool(cf, parents, parentLoader);
 541         try {
 542             Layer layer = new Layer(cf, parents, pool::loaderFor);


 562      * ready to load from these modules before there are any attempts to load
 563      * classes or resources. </p>
 564      *
 565      * <p> Creating a {@code Layer} can fail for the following reasons: </p>
 566      *
 567      * <ul>
 568      *
 569      *     <li><p> Two or more modules with the same package are mapped to the
 570      *     same class loader. </p></li>
 571      *
 572      *     <li><p> A module is mapped to a class loader that already has a
 573      *     module of the same name defined to it. </p></li>
 574      *
 575      *     <li><p> A module is mapped to a class loader that has already
 576      *     defined types in any of the packages in the module. </p></li>
 577      *
 578      * </ul>
 579      *
 580      * <p> In addition, a layer cannot be created if the configuration contains
 581      * a module named "{@code java.base}", a configuration contains a module
 582      * with a package named "{@code java}" or a package name starting with
 583      * "{@code java.}" and the module is mapped to a class loader other than
 584      * the {@link ClassLoader#getPlatformClassLoader() platform class loader},
 585      * or the function to map a module name to a class loader returns
 586      * {@code null}. </p>
 587      *
 588      * <p> If the function to map a module name to class loader throws an error
 589      * or runtime exception then it is propagated to the caller of this method.
 590      * </p>
 591      *
 592      * @apiNote It is implementation specific as to whether creating a Layer
 593      * with this method is an atomic operation or not. Consequentially it is
 594      * possible for this method to fail with some modules, but not all, defined
 595      * to the Java virtual machine.
 596      *
 597      * @param  cf
 598      *         The configuration for the layer
 599      * @param  parentLayers
 600      *         The list of parent layers in search order
 601      * @param  clf
 602      *         The function to map a module name to a class loader
 603      *
 604      * @return A controller that controls the newly created layer
 605      *
 606      * @throws IllegalArgumentException
 607      *         If the parent configurations do not match the configuration of
 608      *         the parent layers, including order
 609      * @throws LayerInstantiationException
 610      *         If creating the layer fails for any of the reasons listed above
 611      * @throws SecurityException
 612      *         If {@code RuntimePermission("getClassLoader")} is denied by
 613      *         the security manager
 614      */
 615     public static Controller defineModules(Configuration cf,
 616                                            List<Layer> parentLayers,
 617                                            Function<String, ClassLoader> clf)
 618     {
 619         List<Layer> parents = new ArrayList<>(parentLayers);
 620         checkConfiguration(cf, parents);


 759                 Layer parent = layer.parents.get(i);
 760                 if (!visited.contains(parent)) {
 761                     visited.add(parent);
 762                     stack.push(parent);
 763                 }
 764             }
 765         }
 766 
 767         this.allLayers = allLayers = Collections.unmodifiableList(allLayers);
 768         return allLayers.stream();
 769     }
 770 
 771     private volatile List<Layer> allLayers;
 772 
 773     /**
 774      * Returns the set of the modules in this layer.
 775      *
 776      * @return A possibly-empty unmodifiable set of the modules in this layer
 777      */
 778     public Set<Module> modules() {
 779         Set<Module> modules = this.modules;
 780         if (modules == null) {
 781             this.modules = modules =
 782                 Collections.unmodifiableSet(new HashSet<>(nameToModule.values()));
 783         }
 784         return modules;
 785     }
 786 
 787     private volatile Set<Module> modules;
 788 
 789 
 790     /**
 791      * Returns the module with the given name in this layer, or if not in this
 792      * layer, the {@linkplain #parents parent} layers. Finding a module in
 793      * parent layers is equivalent to invoking {@code findModule} on each
 794      * parent, in search order, until the module is found or all parents have
 795      * been searched. In a <em>tree of layers</em>  then this is equivalent to
 796      * a depth-first search.
 797      *
 798      * @param  name
 799      *         The name of the module to find
 800      *
 801      * @return The module with the given name or an empty {@code Optional}
 802      *         if there isn't a module with this name in this layer or any
 803      *         parent layer
 804      */
 805     public Optional<Module> findModule(String name) {
 806         Objects.requireNonNull(name);
 807         if (this == EMPTY_LAYER)
 808             return Optional.empty();
 809         Module m = nameToModule.get(name);
 810         if (m != null)
 811             return Optional.of(m);
 812 
 813         return layers()
 814                 .skip(1)  // skip this layer
 815                 .map(l -> l.nameToModule)
 816                 .filter(map -> map.containsKey(name))
 817                 .map(map -> map.get(name))
 818                 .findAny();
 819     }
 820 
 821 
 822     /**
 823      * Returns the {@code ClassLoader} for the module with the given name. If
 824      * a module of the given name is not in this layer then the {@link #parents
 825      * parent} layers are searched in the manner specified by {@link
 826      * #findModule(String) findModule}.
 827      *
 828      * <p> If there is a security manager then its {@code checkPermission}


< prev index next >