< prev index next >

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

Print this page

        

@@ -64,13 +64,11 @@
  *
  * <p> Creating a layer creates a {@link Module} object for each {@link
  * ResolvedModule} in the configuration. For each resolved module that is
  * {@link ResolvedModule#reads() read}, the {@code Module} {@link
  * Module#canRead reads} the corresponding run-time {@code Module}, which may
- * be in the same layer or a {@link #parents() parent} layer. The {@code Module}
- * {@link Module#isExported(String) exports} and {@link Module#isOpen(String)
- * opens} the packages described by its {@link ModuleDescriptor}. </p>
+ * be in the same layer or a {@link #parents() parent} layer. </p>
  *
  * <p> The {@link #defineModulesWithOneLoader defineModulesWithOneLoader} and
  * {@link #defineModulesWithManyLoaders defineModulesWithManyLoaders} methods
  * provide convenient ways to create a {@code Layer} where all modules are
  * mapped to a single class loader or where each module is mapped to its own

@@ -89,10 +87,32 @@
  * The modules in the boot layer are mapped to the bootstrap class loader and
  * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
  * built-in</a> into the Java virtual machine. The boot layer will often be
  * the {@link #parents() parent} when creating additional layers. </p>
  *
+ * <p> Each {@code Module} in a layer is created so that it {@link
+ * Module#isExported(String) exports} and {@link Module#isOpen(String) opens}
+ * the packages described by its {@link ModuleDescriptor}. Qualified exports
+ * (where a package is exported to a set of target modules rather than all
+ * modules) are reified when creating the layer as follows: </p>
+ * <ul>
+ *     <li> If module {@code X} exports a package to {@code Y}, and if the
+ *     runtime {@code Module} {@code X} reads {@code Module} {@code Y}, then
+ *     the package is exported to {@code Module} {@code Y} (which may be in
+ *     the same layer as {@code X} or a parent layer). </li>
+ *
+ *     <li> If module {@code X} exports a package to {@code Y}, and if the
+ *     runtime {@code Module} {@code X} does not read {@code Y} then target
+ *     {@code Y} is located as if by invoking {@link #findModule(String)
+ *     findModule} to find the module in the layer or its parent layers. If
+ *     {@code Y} is found then the package is exported to the instance of
+ *     {@code Y} that was found. If {@code Y} is not found then the qualified
+ *     export is ignored. </li>
+ * </ul>
+ *
+ * <p> Qualified opens are handled in same way as qualified exports. </p>
+ *
  * <p> As when creating a {@code Configuration},
  * {@link ModuleDescriptor#isAutomatic() automatic} modules receive special
  * treatment when creating a layer. An automatic module is created in the
  * Java virtual machine as a {@code Module} that reads every unnamed {@code
  * Module} in the Java virtual machine. </p>

@@ -191,11 +211,11 @@
         public Layer layer() {
             return layer;
         }
 
         private void ensureInLayer(Module source) {
-            if (!layer.modules().contains(source))
+            if (source.getLayer() != layer)
                 throw new IllegalArgumentException(source + " not in layer");
         }
 
 
         /**

@@ -218,13 +238,12 @@
          *         If {@code source} is not in the layer
          *
          * @see Module#addReads
          */
         public Controller addReads(Module source, Module target) {
-            Objects.requireNonNull(source);
-            Objects.requireNonNull(target);
             ensureInLayer(source);
+            Objects.requireNonNull(target);
             Modules.addReads(source, target);
             return this;
         }
 
         /**

@@ -246,13 +265,13 @@
          *         in the source module
          *
          * @see Module#addOpens
          */
         public Controller addOpens(Module source, String pn, Module target) {
-            Objects.requireNonNull(source);
-            Objects.requireNonNull(target);
             ensureInLayer(source);
+            Objects.requireNonNull(pn);
+            Objects.requireNonNull(target);
             Modules.addOpens(source, pn, target);
             return this;
         }
     }
 

@@ -406,21 +425,21 @@
      *     in a specific package. </p></li>
      *
      * </ul>
      *
      * <p> In addition, a layer cannot be created if the configuration contains
-     * a module named "{@code java.base}" or a module with a package name
-     * starting with "{@code java.}". </p>
+     * a module named "{@code java.base}", or a module contains a package named
+     * "{@code java}" or a package with a name starting with "{@code java.}". </p>
      *
      * <p> If there is a security manager then the class loader created by
      * this method will load classes and resources with privileges that are
      * restricted by the calling context of this method. </p>
      *
      * @param  cf
      *         The configuration for the layer
      * @param  parentLayers
-     *         The list parent layers in search order
+     *         The list of parent layers in search order
      * @param  parentLoader
      *         The parent class loader for the class loader created by this
      *         method; may be {@code null} for the bootstrap class loader
      *
      * @return A controller that controls the newly created layer

@@ -483,11 +502,11 @@
      * restricted by the calling context of this method. </p>
      *
      * @param  cf
      *         The configuration for the layer
      * @param  parentLayers
-     *         The list parent layers in search order
+     *         The list of parent layers in search order
      * @param  parentLoader
      *         The parent class loader for each of the class loaders created by
      *         this method; may be {@code null} for the bootstrap class loader
      *
      * @return A controller that controls the newly created layer

@@ -495,12 +514,14 @@
      * @throws IllegalArgumentException
      *         If the parent configurations do not match the configuration of
      *         the parent layers, including order
      * @throws LayerInstantiationException
      *         If the layer cannot be created because the configuration contains
-     *         a module named "{@code java.base}" or a module with a package
-     *         name starting with "{@code java.}"
+     *         a module named "{@code java.base}" or a module contains a package
+     *         named "{@code java}" or a package with a name starting with
+     *         "{@code java.}"
+     *
      * @throws SecurityException
      *         If {@code RuntimePermission("createClassLoader")} or
      *         {@code RuntimePermission("getClassLoader")} is denied by
      *         the security manager
      *

@@ -556,14 +577,15 @@
      *
      * </ul>
      *
      * <p> In addition, a layer cannot be created if the configuration contains
      * a module named "{@code java.base}", a configuration contains a module
-     * with a package name starting with "{@code java.}" is mapped to a class
-     * loader other than the {@link ClassLoader#getPlatformClassLoader()
-     * platform class loader}, or the function to map a module name to a class
-     * loader returns {@code null}. </p>
+     * with a package named "{@code java}" or a package name starting with
+     * "{@code java.}" and the module is mapped to a class loader other than
+     * the {@link ClassLoader#getPlatformClassLoader() platform class loader},
+     * or the function to map a module name to a class loader returns
+     * {@code null}. </p>
      *
      * <p> If the function to map a module name to class loader throws an error
      * or runtime exception then it is propagated to the caller of this method.
      * </p>
      *

@@ -573,11 +595,11 @@
      * to the Java virtual machine.
      *
      * @param  cf
      *         The configuration for the layer
      * @param  parentLayers
-     *         The list parent layers in search order
+     *         The list of parent layers in search order
      * @param  clf
      *         The function to map a module name to a class loader
      *
      * @return A controller that controls the newly created layer
      *

@@ -752,13 +774,19 @@
      * Returns the set of the modules in this layer.
      *
      * @return A possibly-empty unmodifiable set of the modules in this layer
      */
     public Set<Module> modules() {
-        return Collections.unmodifiableSet(
-                nameToModule.values().stream().collect(Collectors.toSet()));
+        Set<Module> modules = this.modules;
+        if (modules == null) {
+            this.modules = modules =
+                Collections.unmodifiableSet(new HashSet<>(nameToModule.values()));
     }
+        return modules;
+    }
+
+    private volatile Set<Module> modules;
 
 
     /**
      * Returns the module with the given name in this layer, or if not in this
      * layer, the {@linkplain #parents parent} layers. Finding a module in

@@ -774,10 +802,12 @@
      *         if there isn't a module with this name in this layer or any
      *         parent layer
      */
     public Optional<Module> findModule(String name) {
         Objects.requireNonNull(name);
+        if (this == EMPTY_LAYER)
+            return Optional.empty();
         Module m = nameToModule.get(name);
         if (m != null)
             return Optional.of(m);
 
         return layers()
< prev index next >