changeset 13555:9b9a710bd9c1

Remove interface ModuleCapableLoader Update ModuleClassLoader to load from modules in a Configuration
author alanb
date Fri, 31 Jul 2015 12:49:25 +0100
parents 0fa5193782bc
children 5271bc3d676c
files src/java.base/share/classes/java/lang/ClassLoader.java src/java.base/share/classes/java/lang/ModuleCapableLoader.java src/java.base/share/classes/java/lang/ModuleClassLoader.java src/java.base/share/classes/java/lang/module/Layer.java src/java.base/share/classes/java/lang/reflect/Module.java src/java.base/share/classes/jdk/internal/misc/BootLoader.java src/java.base/share/classes/jdk/internal/misc/BuiltinClassLoader.java src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java src/jdk.jlink/share/classes/jdk/tools/jlink/TaskHelper.java test/java/lang/ModuleClassLoader/Basic.java test/jdk/jigsaw/functional/container/src/container/container/Main.java test/jdk/jigsaw/module/AutomaticModulesTest.java test/jdk/jigsaw/module/LayerTest.java test/jdk/jigsaw/services/layer/CustomLayerTest.java
diffstat 14 files changed, 240 insertions(+), 228 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Fri Jul 31 12:49:25 2015 +0100
@@ -711,12 +711,7 @@
     Package ensureDefinePackage(String pn) {
         Package p = packages.get(pn);
         if (p == null) {
-            if (this instanceof ModuleCapableLoader) {
-                p = definePackage(pn);
-            } else {
-                p = definePackage(pn, null, null, null,
-                                  null, null, null, null);
-            }
+            p = definePackage(pn);
         }
         return p;
     }
--- a/src/java.base/share/classes/java/lang/ModuleCapableLoader.java	Fri Jul 31 11:34:23 2015 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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;
-
-import java.lang.module.ModuleReference;
-
-/**
- * A class loader implementation that implements this interface is capable
- * of loading classes and resources from one or more named modules.
- *
- * @since 1.9
- */
-
-public interface ModuleCapableLoader {
-
-    /**
-     * Register a module with this class loader so that its classes (and
-     * resources) become visible via this class loader.
-     *
-     * <p> This method is not intended to be invoked directly by applications.
-     * It is instead invoked by {@link java.lang.module.Layer#create
-     * Layer.create} method when creating a layer of modules. </p>
-     *
-     * @throws IllegalStateException
-     *         If a module of the same name is already registered with this
-     *         class loader
-     * @throws SecurityException
-     *         If denied by security manager.
-     */
-    void register(ModuleReference mref);
-}
--- a/src/java.base/share/classes/java/lang/ModuleClassLoader.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/java/lang/ModuleClassLoader.java	Fri Jul 31 12:49:25 2015 +0100
@@ -29,37 +29,42 @@
 import java.io.FilePermission;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.module.Configuration;
 import java.lang.module.ModuleReference;
 import java.lang.module.ModuleReader;
 import java.net.URL;
 import java.nio.ByteBuffer;
-import java.security.*;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.Map;
-import java.util.Optional;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.CodeSigner;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.security.SecureClassLoader;
+import java.util.*;
 import java.util.concurrent.ConcurrentHashMap;
 
 import jdk.internal.misc.BootLoader;
 
 
 /**
- * This {@code ModuleClassLoader} loads classes and resources from one or more named modules.
+ * A {@code ClassLoader} that loads classes and resources from a set of modules
+ * in a configuration.
  *
- * <p>
- * Modules must be registered to this {@code ModuleClassLoader}  by invoking the
- * {@link ModuleCapableLoader#register(ModuleReference)} method
- * so that its classes and resources become visible via this class loader.</p>
- *
- * <p> The delegation model used by this {@code ModuleClassLoader} differs to the regular
- * delegation model. When requested to load a class then this {@code ModuleClassLoader}
- * first checks the modules defined to this class loader. If not found then it delegates
- * the search to the parent class loader.</p>
+ * <p> The delegation model used by this {@code ModuleClassLoader} differs to
+ * the regular delegation model. When requested to load a class then this
+ * {@code ModuleClassLoader} first checks the modules defined to this class
+ * loader. If not found then it delegates the search to the parent class
+ * loader.</p>
  *
  * @since 1.9
  */
 public final class ModuleClassLoader
-    extends SecureClassLoader implements ModuleCapableLoader {
+    extends SecureClassLoader
+{
 
     static {
         ClassLoader.registerAsParallelCapable();
@@ -68,27 +73,121 @@
     // parent ClassLoader
     private final ClassLoader parent;
 
+    // maps a module name to a module reference
+    private final Map<String, ModuleReference> nameToModule;
+
     // maps package name to a module loaded by this class loader
     private final Map<String, ModuleReference> packageToModule;
 
-    // maps a module name to a module reference
-    private final Map<String, ModuleReference> nameToModule;
-
-    // maps a module reference to a module reader
-    private final Map<ModuleReference, ModuleReader> moduleToReader;
+    // maps a module reference to a module reader, populated lazily
+    private final Map<ModuleReference, ModuleReader> moduleToReader
+        = new ConcurrentHashMap<>();
 
     /* The context to be used when loading classes and resources */
     private final AccessControlContext acc;
 
-    private ModuleClassLoader(Void unused, ClassLoader parent) {
+
+
+    private ModuleClassLoader(Void unused,
+                              ClassLoader parent,
+                              Set<ModuleReference> modules)
+    {
         super(parent);
+
+        Map<String, ModuleReference> nameToModule = new HashMap<>();
+        Map<String, ModuleReference> packageToModule = new HashMap<>();
+
+        for (ModuleReference mref : modules) {
+            nameToModule.put(mref.descriptor().name(), mref);
+            mref.descriptor().packages()
+                    .forEach(pn -> packageToModule.put(pn, mref));
+        }
+
         this.parent = parent;
-        this.packageToModule = new ConcurrentHashMap<>();
-        this.nameToModule = new ConcurrentHashMap<>();
-        this.moduleToReader = new ConcurrentHashMap<>();
+        this.packageToModule = packageToModule;
+        this.nameToModule = nameToModule;
         this.acc = AccessController.getContext();
     }
 
+
+    /**
+     * Create a new {@code ModuleClassLoader} that loads classes and resources
+     * from the modules in the given {@code Configuration}. The class loader's
+     * parent is the system class loader.
+     *
+     * <p> If there is a security manager then its {@code checkCreateClassLoader}
+     * is invoked to ensure that creation of a class loader is allowed. </p>
+     *
+     * @throws  SecurityException
+     *          If denied by the security manager
+     */
+    public ModuleClassLoader(Configuration cf) {
+        this(ClassLoader.getSystemClassLoader(), cf);
+    }
+
+    /**
+     * Create a new {@code ModuleClassLoader} that loads classes and resources
+     * from the modules in the given {@code Configuration}. The class loader's
+     * parent is the given class loader.
+     *
+     * <p> If there is a security manager then its {@code checkCreateClassLoader}
+     * is invoked to ensure that creation of a class loader is allowed. </p>
+     *
+     * @throws  SecurityException
+     *          If denied by the security manager
+     */
+    public ModuleClassLoader(ClassLoader parent, Configuration cf) {
+        this(checkCreateClassLoader(), parent, cf.modules());
+    }
+
+    /**
+     * Create a new {@code ModuleClassLoader} that loads classes and resources
+     * from a subset of the modules in the given {@code Configuration}. The
+     * class loader's parent is the system class loader.
+     *
+     * <p> The parameters {@code first} and {@code other} are the names of the
+     * modules in the {@code Configuration} that this class loader should load
+     * from. </p>
+     *
+     * <p> If there is a security manager then its {@code checkCreateClassLoader}
+     * is invoked to ensure that creation of a class loader is allowed. </p>
+     *
+     * @throws  IllegalArgumentException
+     *          If any of the modules are not in the given Configuration
+     * @throws  SecurityException
+     *          If denied by the security manager
+     */
+    public ModuleClassLoader(Configuration cf, String first, String... other) {
+        this(checkCreateClassLoader(),
+             ClassLoader.getSystemClassLoader(),
+             collect(cf, first, other));
+    }
+
+    /**
+     * Create a new {@code ModuleClassLoader} that loads classes and resources
+     * from a subset of the modules in the given {@code Configuration}. The
+     * class loader's parent is the given class loader
+     *
+     * <p> The parameters {@code first} and {@code other} are the names of the
+     * modules in the {@code Configuration} that this class loader should load
+     * from. </p>
+     *
+     * <p> If there is a security manager then its {@code checkCreateClassLoader}
+     * is invoked to ensure that creation of a class loader is allowed. </p>
+     *
+     * @throws  IllegalArgumentException
+     *          If any of the modules are not in the given Configuration
+     * @throws  SecurityException
+     *          If denied by the security manager
+     */
+    public ModuleClassLoader(ClassLoader parent,
+                             Configuration cf,
+                             String first,
+                             String... other) {
+        this(checkCreateClassLoader(), parent, collect(cf, first, other));
+    }
+
+
     private static Void checkCreateClassLoader() {
         SecurityManager security = System.getSecurityManager();
         if (security != null) {
@@ -97,59 +196,27 @@
         return null;
     }
 
-    /**
-     * Create a new {@code ModuleClassLoader} using
-     * the {@linkplain ClassLoader#getSystemClassLoader() application class loader}
-     * as the parent class loader.
-     *
-     * <p>
-     * If there is a security manager, its {@link SecurityManager#checkCreateClassLoader()
-     * checkCreateClassLoader} method is invoked.
-     *
-     * @throws  SecurityException
-     *          If a security manager exists and its
-     *          {@code checkCreateClassLoader} method doesn't allow creation
-     *          of a new class loader.
-     */
-    public ModuleClassLoader() {
-        this(checkCreateClassLoader(), ClassLoader.getSystemClassLoader());
+    private static Set<ModuleReference> collect(Configuration cf,
+                                                String first,
+                                                String... other)
+    {
+        Set<ModuleReference> modules = new HashSet<>();
+
+        Optional<ModuleReference> omref = cf.findModule(first);
+        if (!omref.isPresent())
+            throw new IllegalArgumentException(first + " not in Configuration");
+        modules.add(omref.get());
+
+        for (String mn : other) {
+            omref = cf.findModule(mn);
+            if (!omref.isPresent())
+                throw new IllegalArgumentException(first + " not in Configuration");
+            modules.add(omref.get());
+        }
+
+        return modules;
     }
 
-    /**
-     * Create a new {@code ModuleClassLoader} using the specified parent class loader
-     * for delegation.
-     *
-     * <p>
-     * If there is a security manager, its {@link SecurityManager#checkCreateClassLoader()
-     * checkCreateClassLoader} method is invoked.
-     *
-     * @param parent parent class loader
-     *
-     * @throws  SecurityException
-     *          If a security manager exists and its
-     *          {@code checkCreateClassLoader} method doesn't allow creation
-     *          of a new class loader.
-     */
-    public ModuleClassLoader(ClassLoader parent) {
-        this(checkCreateClassLoader(), parent);
-    }
-
-    @Override
-    public void register(ModuleReference mref) {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            RuntimePermission perm = new RuntimePermission("registerSystemModule");
-            sm.checkPermission(perm);
-        }
-
-        String mn = mref.descriptor().name();
-        if (nameToModule.containsKey(mn))
-            throw new IllegalStateException("Module " + mn
-                    + " already defined in this class loader");
-        nameToModule.put(mn, mref);
-        mref.descriptor().packages()
-                .forEach(p -> packageToModule.put(p, mref));
-    }
 
     // -- finding resources
 
@@ -167,17 +234,18 @@
      */
     @Override
     public InputStream getResourceAsStream(String moduleName, String name)
-            throws IOException {
+        throws IOException
+    {
         ModuleReference mref = nameToModule.get(moduleName);
         if (mref != null) {
             try {
                 return AccessController.doPrivileged(
-                        new PrivilegedExceptionAction<InputStream>() {
-                            @Override
-                            public InputStream run() throws IOException {
-                                return moduleReaderFor(mref).open(name).orElse(null);
-                            }
-                        }, acc);
+                    new PrivilegedExceptionAction<InputStream>() {
+                        @Override
+                        public InputStream run() throws IOException {
+                            return moduleReaderFor(mref).open(name).orElse(null);
+                        }
+                    }, acc);
             } catch (PrivilegedActionException pae) {
                 throw (IOException) pae.getCause();
             }
@@ -236,19 +304,18 @@
     }
 
     /**
-     * Loads the class with the specified <a href="ClassLoader.html#name">binary name</a>
-     * from a module defined to this class loader.
+     * Loads the class with the specified <a href="ClassLoader.html#name">binary
+     * name</a> from a module defined to this class loader.
      *
-     * <p>
-     * This {@code ModuleClassLoader} first checks the modules defined to this class loader.
-     * If not found then it delegates the search to the parent class loader.
+     * <p> This {@code ModuleClassLoader} first checks the modules defined to
+     * this class loader. If not found then it delegates the search to the
+     * parent class loader.
      *
      * @inheritDoc
-     *
      */
     @Override
     protected Class<?> loadClass(String name, boolean resolve)
-            throws ClassNotFoundException
+        throws ClassNotFoundException
     {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -267,12 +334,12 @@
 
 
     /**
-     * Loads the class with the specified <a href="ClassLoader.html#name">binary name</a>
-     * from a module defined to this class loader.
-     * <p>
-     * This {@code ModuleClassLoader} first checks the modules defined to this class loader.
-     * If not found then it delegates the search to the parent class loader.  If not
-     * found, it returns {@code null}.
+     * Loads the class with the specified <a href="ClassLoader.html#name">binary
+     * name</a> from a module defined to this class loader.
+     *
+     * <p> This {@code ModuleClassLoader} first checks the modules defined to
+     * this class loader. If not found then it delegates the search to the
+     * parent class loader.  If not found, it returns {@code null}.
      */
     private Class<?> loadClassOrNull(String name, boolean resolve) {
         synchronized (getClassLoadingLock(name)) {
@@ -383,8 +450,8 @@
      * @param name  name of the package to be defined.
      * @return {@code Package} object of the given name
      *
-     * @throws IllegalArgumentException if a duplicated {@code Package} of the given name
-     *         is defined in different module by this class loader.
+     * @throws IllegalArgumentException if a duplicated {@code Package} of the
+     *         given name is defined in different module by this class loader.
      */
     @Override
     protected Package definePackage(String name) {
--- a/src/java.base/share/classes/java/lang/module/Layer.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/java/lang/module/Layer.java	Fri Jul 31 12:49:25 2015 +0100
@@ -55,9 +55,9 @@
  *                                 finder,
  *                                 "myapp");
  *
- *     ClassLoader loader = new ModuleClassLoader();
+ *     ClassLoader loader = new ModuleClassLoader(cf);
  *
- *     Layer layer = Layer.create(cf, m -> loader);
+ *     Layer layer = Layer.create(cf, mn -> loader);
  *
  *     Class<?> c = layer.findLoader("myapp").loadClass("app.Main");
  * }</pre>
@@ -111,13 +111,14 @@
      *
      * <p> Modules are mapped to module-capable class loaders by means of the
      * given {@code ClassLoaderFinder} and defined to the Java virtual machine.
-     * This method also registers modules to their class loader by invoking
-     * the class loader's {@link ModuleCapableLoader#register register} method.
-     * </p>
+     * The caller of this method must arrange for the class loaders to be
+     * ready to load from these modules before attempting to load classes or
+     * resources. This can be before or after the {@code Layer} is created. </p>
      *
      * <p> Creating a {@code Layer} may fail for several reasons: </p>
      *
      * <ul>
+     *
      *     <li> Two or more modules with the same package (exported or
      *          concealed) are mapped to the same class loader. </li>
      *
--- a/src/java.base/share/classes/java/lang/reflect/Module.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/java/lang/reflect/Module.java	Fri Jul 31 12:49:25 2015 +0100
@@ -788,14 +788,6 @@
             Module m = defineModule(loader, mref);
             modules.put(name, m);
             loaders.put(name, loader);
-
-            // register all modules (except java.base) with its class loader
-            if (loader == null) {
-                if (!mref.descriptor().name().equals("java.base"))
-                    BootLoader.register(mref);
-            } else {
-                ((ModuleCapableLoader) loader).register(mref);
-            }
         }
 
         // setup readability and exports
--- a/src/java.base/share/classes/jdk/internal/misc/BootLoader.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/jdk/internal/misc/BootLoader.java	Fri Jul 31 12:49:25 2015 +0100
@@ -66,8 +66,8 @@
      * Register a module with this class loader so that its classes (and
      * resources) become visible via this class loader.
      */
-    public static void register(ModuleReference mref) {
-        ClassLoaders.bootLoader().register(mref);
+    public static void loadModule(ModuleReference mref) {
+        ClassLoaders.bootLoader().loadModule(mref);
         if (baseReference == null) {
             if (!mref.descriptor().name().equals("java.base"))
                 throw new InternalError();
--- a/src/java.base/share/classes/jdk/internal/misc/BuiltinClassLoader.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/jdk/internal/misc/BuiltinClassLoader.java	Fri Jul 31 12:49:25 2015 +0100
@@ -66,7 +66,7 @@
  * ClassLoader type.
  *
  * <p> This ClassLoader supports loading of classes and resources from modules.
- * Modules are defined to the ClassLoader by invoking the {@link #defineModule}
+ * Modules are defined to the ClassLoader by invoking the {@link #loadModule}
  * method. Defining a module to this ClassLoader has the effect of making the
  * types in the module visible. </p>
  *
@@ -84,8 +84,9 @@
  * any overlapping packages with modules defined to the parent or the boot class
  * loader. </p>
  */
-class BuiltinClassLoader
-    extends SecureClassLoader implements ModuleCapableLoader
+
+public class BuiltinClassLoader
+    extends SecureClassLoader
 {
 
     static {
@@ -163,25 +164,16 @@
     }
 
     /**
-     * Register a module this this class loader. This has the effect
-     * of making the types in the module visible.
+     * Register a module this this class loader. This has the effect of making
+     * the types in the module visible.
      */
-    @Override
-    public void register(ModuleReference mref) {
-
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            RuntimePermission perm = new RuntimePermission("registerSystemModule");
-            sm.checkPermission(perm);
+    public void loadModule(ModuleReference mref) {
+        String mn = mref.descriptor().name();
+        if (nameToModule.putIfAbsent(mn, mref) != null) {
+            throw new InternalError(mn + " already defined to this loader");
         }
 
-        String mn = mref.descriptor().name();
-        if (nameToModule.containsKey(mn))
-            throw new IllegalStateException("Module " + mn
-                                            + " already defined in this class loader");
-        nameToModule.put(mn, mref);
         LoadedModule loadedModule = new LoadedModule(mref);
-
         for (String pn : mref.descriptor().packages()) {
             packageToModule.put(pn, loadedModule);
         }
--- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java	Fri Jul 31 12:49:25 2015 +0100
@@ -42,6 +42,7 @@
 import java.util.stream.Collectors;
 
 import jdk.internal.misc.BootLoader;
+import jdk.internal.misc.BuiltinClassLoader;
 import jdk.internal.misc.Modules;
 import sun.misc.PerfCounter;
 import sun.misc.SharedSecrets;
@@ -72,13 +73,22 @@
     public static void boot() {
         long t0 = System.nanoTime();
 
-        // -upgrademodulepath option specified to launcher
-        ModuleFinder upgradeModulePath =
-            createModulePathFinder("java.upgrade.module.path");
-
         // system module path, aka the installed modules
         ModuleFinder systemModulePath = ModuleFinder.ofInstalled();
 
+        // Once we have the system module path then we define the base module
+        // to the boot loader. We do this here so that resources in the base
+        // module can be located for error messages that may happen from here
+        // on.
+        Optional<ModuleReference> obase = systemModulePath.find(JAVA_BASE);
+        if (!obase.isPresent())
+            throw new InternalError(JAVA_BASE + " not found");
+        BootLoader.loadModule(obase.get());
+
+        // -upgrademodulepath option specified to launcher
+        ModuleFinder upgradeModulePath
+            = createModulePathFinder("java.upgrade.module.path");
+
         // -modulepath option specified to the launcher
         ModuleFinder appModulePath = createModulePathFinder("java.module.path");
 
@@ -89,14 +99,6 @@
         if (appModulePath != null)
             finder = ModuleFinder.concat(finder, appModulePath);
 
-        // Once the finder is created then we find the base module and define
-        // it to the boot loader. We do this here so that resources in the
-        // base module can be located for error messages that may happen
-        // from here on.
-        Optional<ModuleReference> obase = finder.find(JAVA_BASE);
-        if (!obase.isPresent())
-            throw new InternalError(JAVA_BASE + " not found");
-        BootLoader.register(obase.get());
 
         // launcher -m option to specify the initial module
         String mainModule = null;
@@ -202,6 +204,17 @@
         // define modules to VM/runtime
         Layer bootLayer = Layer.create(cf, clf);
 
+        // define the module to its class loader, except java.base
+        for (ModuleReference mref : cf.modules()) {
+            String name = mref.descriptor().name();
+            ClassLoader cl = clf.loaderForModule(name);
+            if (cl == null) {
+                if (!name.equals(JAVA_BASE)) BootLoader.loadModule(mref);
+            } else {
+                ((BuiltinClassLoader)cl).loadModule(mref);
+            }
+        }
+
         // if -XaddExports is specified then process the value to export
         // additional API packages
         propValue= System.getProperty("jdk.launcher.addexports");
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/TaskHelper.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/TaskHelper.java	Fri Jul 31 12:49:25 2015 +0100
@@ -165,12 +165,12 @@
                 ModuleFinder finder = ModuleFinder.of(paths);
 
                 Configuration cf
-                        = Configuration.resolve(ModuleFinder.empty(), Layer.boot(), finder);
+                    = Configuration.resolve(ModuleFinder.empty(), Layer.boot(), finder);
 
                 cf = cf.bind();
 
-                ClassLoader cl = new ModuleClassLoader();
-                pluginsLayer = Layer.create(cf, l -> cl);
+                ClassLoader cl = new ModuleClassLoader(cf);
+                pluginsLayer = Layer.create(cf, mn -> cl);
             }
 
             Map<String, List<String>> seen = new HashMap<>();
--- a/test/java/lang/ModuleClassLoader/Basic.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/test/java/lang/ModuleClassLoader/Basic.java	Fri Jul 31 12:49:25 2015 +0100
@@ -30,6 +30,9 @@
  */
 
 import java.io.FilePermission;
+import java.lang.module.Configuration;
+import java.lang.module.Layer;
+import java.lang.module.ModuleFinder;
 import java.net.URL;
 import java.security.AccessControlException;
 import java.security.Permission;
@@ -67,8 +70,12 @@
     }
 
     static void test(ClassLoader parent, boolean succeed) throws ClassNotFoundException {
+
+        Configuration cf = Configuration.resolve(ModuleFinder.empty(),
+                                                 Layer.empty(),
+                                                 ModuleFinder.empty());
         try {
-            ModuleClassLoader loader = new ModuleClassLoader(parent);
+            ModuleClassLoader loader = new ModuleClassLoader(parent, cf);
             if (!succeed) {
                 throw new RuntimeException("Expected SecurityException not thrown");
             }
--- a/test/jdk/jigsaw/functional/container/src/container/container/Main.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/test/jdk/jigsaw/functional/container/src/container/container/Main.java	Fri Jul 31 12:49:25 2015 +0100
@@ -81,10 +81,10 @@
           .forEach(md -> System.out.format("  %s%n", md.name()));
 
         // choose a class loader
-        ModuleClassLoader loader = new ModuleClassLoader();
+        ModuleClassLoader loader = new ModuleClassLoader(cf);
 
         // reify the configuration as a Layer
-        Layer layer = Layer.create(cf, m -> loader);
+        Layer layer = Layer.create(cf, mn -> loader);
 
         // invoke application main method
         Class<?> c = layer.findLoader(appModuleName).loadClass(appMainClass);
--- a/test/jdk/jigsaw/module/AutomaticModulesTest.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/test/jdk/jigsaw/module/AutomaticModulesTest.java	Fri Jul 31 12:49:25 2015 +0100
@@ -264,7 +264,7 @@
         assertTrue(cf.descriptors().size() == 3);
 
         // each module gets its own loader
-        Layer layer = Layer.create(cf, m -> new ModuleClassLoader());
+        Layer layer = Layer.create(cf, mn -> new ModuleClassLoader(cf, mn));
 
         Module m2 = layer.findModule("m2").get();
         assertTrue(m2.isNamed());
--- a/test/jdk/jigsaw/module/LayerTest.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/test/jdk/jigsaw/module/LayerTest.java	Fri Jul 31 12:49:25 2015 +0100
@@ -130,9 +130,9 @@
                                                  "m1");
 
         // map each module to its own class loader for this test
-        ClassLoader loader1 = new ModuleClassLoader();
-        ClassLoader loader2 = new ModuleClassLoader();
-        ClassLoader loader3 = new ModuleClassLoader();
+        ClassLoader loader1 = new ModuleClassLoader(cf, "m1");
+        ClassLoader loader2 = new ModuleClassLoader(cf, "m2");
+        ClassLoader loader3 = new ModuleClassLoader(cf, "m3");
         Map<String, ClassLoader> map = new HashMap<>();
         map.put("m1", loader1);
         map.put("m2", loader2);
@@ -204,9 +204,9 @@
                                                  ModuleFinder.empty(),
                                                  "m1");
 
-        ClassLoader loader = new ModuleClassLoader();
+        ClassLoader loader = new ModuleClassLoader(cf);
 
-        Layer layer = Layer.create(cf, m -> loader);
+        Layer layer = Layer.create(cf, mn -> loader);
 
         // configuration
         assertTrue(layer.configuration().get() == cf);
@@ -265,12 +265,12 @@
         assertTrue(cf.descriptors().size() == 2);
 
         // one loader per module, should be okay
-        Layer.create(cf, m -> new ModuleClassLoader());
+        Layer.create(cf, mn -> new ModuleClassLoader(cf, mn));
 
         // same class loader
         try {
-            ClassLoader loader = new ModuleClassLoader();
-            Layer.create(cf, m -> loader);
+            ClassLoader loader = new ModuleClassLoader(cf);
+            Layer.create(cf, mn -> loader);
             assertTrue(false);
         } catch (LayerInstantiationException expected) { }
     }
@@ -314,11 +314,11 @@
         assertTrue(cf.descriptors().size() == 4);
 
         // one loader per module
-        Layer.create(cf, m -> new ModuleClassLoader());
+        Layer.create(cf, mn -> new ModuleClassLoader(cf, mn));
 
         // m1 & m2 in one loader, m3 & m4 in another loader
-        ClassLoader loader1 = new ModuleClassLoader();
-        ClassLoader loader2 = new ModuleClassLoader();
+        ClassLoader loader1 = new ModuleClassLoader(cf, "m1");
+        ClassLoader loader2 = new ModuleClassLoader(cf, "m2");
         Map<String, ClassLoader> map = new HashMap<>();
         map.put("m1", loader1);
         map.put("m2", loader1);
@@ -328,8 +328,8 @@
 
         // same loader
         try {
-            ClassLoader loader = new ModuleClassLoader();
-            Layer.create(cf, m -> loader);
+            ClassLoader loader = new ModuleClassLoader(cf);
+            Layer.create(cf, mn -> loader);
             assertTrue(false);
         } catch (LayerInstantiationException expected) { }
     }
@@ -353,7 +353,8 @@
             = Configuration.resolve(finder, Layer.boot(), ModuleFinder.empty(), "m1");
         assertTrue(cf.descriptors().size() == 1);
 
-        Layer layer = Layer.create(cf, m -> new ModuleClassLoader());
+        ClassLoader loader = new ModuleClassLoader(cf);
+        Layer layer = Layer.create(cf, mn -> loader);
         assertTrue(layer.modules().size() == 1);
    }
 
--- a/test/jdk/jigsaw/services/layer/CustomLayerTest.java	Fri Jul 31 11:34:23 2015 +0100
+++ b/test/jdk/jigsaw/services/layer/CustomLayerTest.java	Fri Jul 31 12:49:25 2015 +0100
@@ -52,10 +52,8 @@
 
         cf = cf.bind();
 
-        // create the Layer with the module loaded by the system class loader
-        ClassLoader scl = ClassLoader.getSystemClassLoader();
-        ModuleReference mref = cf.findModule(moduleName).get();
-        Layer layer = Layer.create(cf, k -> scl);
+        ClassLoader loader = new ModuleClassLoader(cf);
+        Layer layer = Layer.create(cf, mn -> loader);
 
         ServiceLoader<ScriptEngineFactory> sl;
         ScriptEngineFactory factory;