diff -r 2c33418a6d57 -r 83b611b88ac8 jdk/src/java.base/share/classes/java/lang/reflect/Layer.java --- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Thu Apr 06 17:01:03 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,949 +0,0 @@ -/* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.reflect; - -import java.lang.module.Configuration; -import java.lang.module.ModuleDescriptor; -import java.lang.module.ResolvedModule; -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Deque; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import jdk.internal.loader.ClassLoaderValue; -import jdk.internal.loader.Loader; -import jdk.internal.loader.LoaderPool; -import jdk.internal.misc.SharedSecrets; -import jdk.internal.module.Modules; -import jdk.internal.module.ServicesCatalog; -import sun.security.util.SecurityConstants; - - -/** - * A layer of modules in the Java virtual machine. - * - *
A layer is created from a graph of modules in a {@link Configuration} - * and a function that maps each module to a {@link ClassLoader}. - * Creating a layer informs the Java virtual machine about the classes that - * may be loaded from the modules so that the Java virtual machine knows which - * module that each class is a member of.
- * - *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 {@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 - * class loader. The {@link #defineModules defineModules} method is for more - * advanced cases where modules are mapped to custom class loaders by means of - * a function specified to the method. Each of these methods has an instance - * and static variant. The instance methods create a layer with the receiver - * as the parent layer. The static methods are for more advanced cases where - * there can be more than one parent layer or where a {@link Layer.Controller - * Controller} is needed to control modules in the layer.
- * - *A Java virtual machine has at least one non-empty layer, the {@link - * #boot() boot} layer, that is created when the Java virtual machine is - * started. The boot layer contains module {@code java.base} and is the only - * layer in the Java virtual machine with a module named "{@code java.base}". - * The modules in the boot layer are mapped to the bootstrap class loader and - * other class loaders that are - * built-in into the Java virtual machine. The boot layer will often be - * the {@link #parents() parent} when creating additional layers.
- * - *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:
- *Qualified opens are handled in same way as qualified exports.
- * - *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.
- * - *Unless otherwise specified, passing a {@code null} argument to a method - * in this class causes a {@link NullPointerException NullPointerException} to - * be thrown.
- * - *This example creates a configuration by resolving a module named - * "{@code myapp}" with the configuration for the boot layer as the parent. It - * then creates a new layer with the modules in this configuration. All modules - * are defined to the same class loader.
- * - *{@code - * ModuleFinder finder = ModuleFinder.of(dir1, dir2, dir3); - * - * Layer parent = Layer.boot(); - * - * Configuration cf = parent.configuration().resolve(finder, ModuleFinder.of(), Set.of("myapp")); - * - * ClassLoader scl = ClassLoader.getSystemClassLoader(); - * - * Layer layer = parent.defineModulesWithOneLoader(cf, scl); - * - * Class> c = layer.findLoader("myapp").loadClass("app.Main"); - * }- * - * @since 9 - * @spec JPMS - * @see Module#getLayer() - */ - -public final class Layer { - - // the empty Layer - private static final Layer EMPTY_LAYER - = new Layer(Configuration.empty(), List.of(), null); - - // the configuration from which this Layer was created - private final Configuration cf; - - // parent layers, empty in the case of the empty layer - private final List
Unless otherwise specified, passing a {@code null} argument to a - * method in this class causes a {@link NullPointerException - * NullPointerException} to be thrown.
- * - * @apiNote Care should be taken with {@code Controller} objects, they - * should never be shared with untrusted code. - * - * @since 9 - * @spec JPMS - */ - public static final class Controller { - private final Layer layer; - - Controller(Layer layer) { - this.layer = layer; - } - - /** - * Returns the layer that this object controls. - * - * @return the layer - */ - public Layer layer() { - return layer; - } - - private void ensureInLayer(Module source) { - if (source.getLayer() != layer) - throw new IllegalArgumentException(source + " not in layer"); - } - - - /** - * Updates module {@code source} in the layer to read module - * {@code target}. This method is a no-op if {@code source} already - * reads {@code target}. - * - * @implNote Read edges added by this method are weak - * and do not prevent {@code target} from being GC'ed when {@code source} - * is strongly reachable. - * - * @param source - * The source module - * @param target - * The target module to read - * - * @return This controller - * - * @throws IllegalArgumentException - * If {@code source} is not in the layer - * - * @see Module#addReads - */ - public Controller addReads(Module source, Module target) { - ensureInLayer(source); - Objects.requireNonNull(target); - Modules.addReads(source, target); - return this; - } - - /** - * Updates module {@code source} in the layer to open a package to - * module {@code target}. This method is a no-op if {@code source} - * already opens the package to at least {@code target}. - * - * @param source - * The source module - * @param pn - * The package name - * @param target - * The target module to read - * - * @return This controller - * - * @throws IllegalArgumentException - * If {@code source} is not in the layer or the package is not - * in the source module - * - * @see Module#addOpens - */ - public Controller addOpens(Module source, String pn, Module target) { - ensureInLayer(source); - Objects.requireNonNull(pn); - Objects.requireNonNull(target); - Modules.addOpens(source, pn, target); - return this; - } - } - - - /** - * Creates a new layer, with this layer as its parent, by defining the - * modules in the given {@code Configuration} to the Java virtual machine. - * This method creates one class loader and defines all modules to that - * class loader. The {@link ClassLoader#getParent() parent} of each class - * loader is the given parent class loader. This method works exactly as - * specified by the static {@link - * #defineModulesWithOneLoader(Configuration,List,ClassLoader) - * defineModulesWithOneLoader} method when invoked with this layer as the - * parent. In other words, if this layer is {@code thisLayer} then this - * method is equivalent to invoking: - *{@code - * Layer.defineModulesWithOneLoader(cf, List.of(thisLayer), parentLoader).layer(); - * }- * - * @param cf - * The configuration for the layer - * @param parentLoader - * The parent class loader for the class loader created by this - * method; may be {@code null} for the bootstrap class loader - * - * @return The newly created layer - * - * @throws IllegalArgumentException - * If the parent of the given configuration is not the configuration - * for this layer - * @throws LayerInstantiationException - * If the layer cannot be created for any of the reasons specified - * by the static {@code defineModulesWithOneLoader} method - * @throws SecurityException - * If {@code RuntimePermission("createClassLoader")} or - * {@code RuntimePermission("getClassLoader")} is denied by - * the security manager - * - * @see #findLoader - */ - public Layer defineModulesWithOneLoader(Configuration cf, - ClassLoader parentLoader) { - return defineModulesWithOneLoader(cf, List.of(this), parentLoader).layer(); - } - - - /** - * Creates a new layer, with this layer as its parent, by defining the - * modules in the given {@code Configuration} to the Java virtual machine. - * Each module is defined to its own {@link ClassLoader} created by this - * method. The {@link ClassLoader#getParent() parent} of each class loader - * is the given parent class loader. This method works exactly as specified - * by the static {@link - * #defineModulesWithManyLoaders(Configuration,List,ClassLoader) - * defineModulesWithManyLoaders} method when invoked with this layer as the - * parent. In other words, if this layer is {@code thisLayer} then this - * method is equivalent to invoking: - *
{@code - * Layer.defineModulesWithManyLoaders(cf, List.of(thisLayer), parentLoader).layer(); - * }- * - * @param cf - * The configuration for the layer - * @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 The newly created layer - * - * @throws IllegalArgumentException - * If the parent of the given configuration is not the configuration - * for this layer - * @throws LayerInstantiationException - * If the layer cannot be created for any of the reasons specified - * by the static {@code defineModulesWithManyLoaders} method - * @throws SecurityException - * If {@code RuntimePermission("createClassLoader")} or - * {@code RuntimePermission("getClassLoader")} is denied by - * the security manager - * - * @see #findLoader - */ - public Layer defineModulesWithManyLoaders(Configuration cf, - ClassLoader parentLoader) { - return defineModulesWithManyLoaders(cf, List.of(this), parentLoader).layer(); - } - - - /** - * Creates a new layer, with this layer as its parent, by defining the - * modules in the given {@code Configuration} to the Java virtual machine. - * Each module is mapped, by name, to its class loader by means of the - * given function. This method works exactly as specified by the static - * {@link #defineModules(Configuration,List,Function) defineModules} - * method when invoked with this layer as the parent. In other words, if - * this layer is {@code thisLayer} then this method is equivalent to - * invoking: - *
{@code - * Layer.defineModules(cf, List.of(thisLayer), clf).layer(); - * }- * - * @param cf - * The configuration for the layer - * @param clf - * The function to map a module name to a class loader - * - * @return The newly created layer - * - * @throws IllegalArgumentException - * If the parent of the given configuration is not the configuration - * for this layer - * @throws LayerInstantiationException - * If the layer cannot be created for any of the reasons specified - * by the static {@code defineModules} method - * @throws SecurityException - * If {@code RuntimePermission("getClassLoader")} is denied by - * the security manager - */ - public Layer defineModules(Configuration cf, - Function
The class loader created by this method implements direct - * delegation when loading types from modules. When its {@link - * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to - * load a class then it uses the package name of the class to map it to a - * module. This may be a module in this layer and hence defined to the same - * class loader. It may be a package in a module in a parent layer that is - * exported to one or more of the modules in this layer. The class - * loader delegates to the class loader of the module, throwing {@code - * ClassNotFoundException} if not found by that class loader. - * When {@code loadClass} is invoked to load classes that do not map to a - * module then it delegates to the parent class loader.
- * - *Attempting to create a layer with all modules defined to the same - * class loader can fail for the following reasons: - * - *
Overlapping packages: Two or more modules in the - * configuration have the same package.
Split delegation: The resulting class loader would - * need to delegate to more than one class loader in order to load types - * in a specific package.
In addition, a layer cannot be created if the configuration contains - * 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.}".
- * - *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.
- * - * @param cf - * The configuration for the layer - * @param parentLayers - * 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 - * - * @throws IllegalArgumentException - * If the parent configurations do not match the configuration of - * the parent layers, including order - * @throws LayerInstantiationException - * If all modules cannot be defined to the same class loader for any - * of the reasons listed above - * @throws SecurityException - * If {@code RuntimePermission("createClassLoader")} or - * {@code RuntimePermission("getClassLoader")} is denied by - * the security manager - * - * @see #findLoader - */ - public static Controller defineModulesWithOneLoader(Configuration cf, - ListThe class loaders created by this method implement direct - * delegation when loading types from modules. When {@link - * ClassLoader#loadClass(String, boolean) loadClass} method is invoked to - * load a class then it uses the package name of the class to map it to a - * module. The package may be in the module defined to the class loader. - * The package may be exported by another module in this layer to the - * module defined to the class loader. It may be in a package exported by a - * module in a parent layer. The class loader delegates to the class loader - * of the module, throwing {@code ClassNotFoundException} if not found by - * that class loader. - * When {@code loadClass} is invoked to load classes that do not map to a - * module then it delegates to the parent class loader.
- * - *If there is a security manager then the class loaders created by - * this method will load classes and resources with privileges that are - * restricted by the calling context of this method.
- * - * @param cf - * The configuration for the layer - * @param parentLayers - * 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 - * - * @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 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 - * - * @see #findLoader - */ - public static Controller defineModulesWithManyLoaders(Configuration cf, - ListThe class loader delegation implemented by the class loaders must - * respect module readability. The class loaders should be - * {@link ClassLoader#registerAsParallelCapable parallel-capable} so as to - * avoid deadlocks during class loading. In addition, the entity creating - * a new layer with this method should arrange that the class loaders be - * ready to load from these modules before there are any attempts to load - * classes or resources.
- * - *Creating a {@code Layer} can fail for the following reasons:
- * - *Two or more modules with the same package are mapped to the - * same class loader.
A module is mapped to a class loader that already has a - * module of the same name defined to it.
A module is mapped to a class loader that has already - * defined types in any of the packages in the module.
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 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}.
- * - *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. - *
- * - * @apiNote It is implementation specific as to whether creating a Layer - * with this method is an atomic operation or not. Consequentially it is - * possible for this method to fail with some modules, but not all, defined - * to the Java virtual machine. - * - * @param cf - * The configuration for the layer - * @param parentLayers - * 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 - * - * @throws IllegalArgumentException - * If the parent configurations do not match the configuration of - * the parent layers, including order - * @throws LayerInstantiationException - * If creating the layer fails for any of the reasons listed above - * @throws SecurityException - * If {@code RuntimePermission("getClassLoader")} is denied by - * the security manager - */ - public static Controller defineModules(Configuration cf, - ListIf there is a security manager then its {@code checkPermission} - * method is called with a {@code RuntimePermission("getClassLoader")} - * permission to check that the caller is allowed to get access to the - * class loader.
- * - * @apiNote This method does not return an {@code Optional