# HG changeset patch # User alanb # Date 1464202683 -3600 # Node ID 8c49d605b02426edeb26b96836db3ee3b816e893 # Parent bf65323537b2c1c1730548bf3eab6996004fbf94 8150668: Layer.defineModulesXXX with a Configuration containing java.base throws undocumented exception Reviewed-by: chegar, mchung diff -r bf65323537b2 -r 8c49d605b024 jdk/src/java.base/share/classes/java/lang/reflect/Layer.java --- a/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Wed May 25 17:07:13 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Layer.java Wed May 25 19:58:03 2016 +0100 @@ -75,11 +75,12 @@ * *
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 system modules, including {@code java.base}, are in - * the boot layer. 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 #parent() parent} when - * creating additional layers.
+ * 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 #parent() parent} when creating additional layers. * *As when creating a {@code Configuration}, * {@link ModuleDescriptor#isAutomatic() automatic} modules receive @@ -204,7 +205,8 @@ * for this layer * @throws LayerInstantiationException * If all modules cannot be defined to the same class loader for any - * of the reasons listed above + * of the reasons listed above or the layer cannot be created because + * the configuration contains a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("createClassLoader")} or * {@code RuntimePermission("getClassLoader")} is denied by @@ -219,14 +221,13 @@ checkCreateClassLoaderPermission(); checkGetClassLoaderPermission(); - Loader loader; try { - loader = new Loader(cf.modules(), parentLoader); + Loader loader = new Loader(cf.modules(), parentLoader); loader.initRemotePackageMap(cf, this); + return new Layer(cf, this, mn -> loader); } catch (IllegalArgumentException e) { throw new LayerInstantiationException(e.getMessage()); } - return new Layer(cf, this, mn -> loader); } @@ -266,6 +267,9 @@ * @throws IllegalArgumentException * If the parent of the given configuration is not the configuration * for this layer + * @throws LayerInstantiationException + * If the layer cannot be created because the configuration contains + * a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("createClassLoader")} or * {@code RuntimePermission("getClassLoader")} is denied by @@ -281,7 +285,11 @@ checkGetClassLoaderPermission(); LoaderPool pool = new LoaderPool(cf, this, parentLoader); - return new Layer(cf, this, pool::loaderFor); + try { + return new Layer(cf, this, pool::loaderFor); + } catch (IllegalArgumentException e) { + throw new LayerInstantiationException(e.getMessage()); + } } @@ -330,7 +338,8 @@ * for this layer * @throws LayerInstantiationException * If creating the {@code Layer} fails for any of the reasons - * listed above + * listed above or the layer cannot be created because the + * configuration contains a module named "{@code java.base}" * @throws SecurityException * If {@code RuntimePermission("getClassLoader")} is denied by * the security manager diff -r bf65323537b2 -r 8c49d605b024 jdk/src/java.base/share/classes/java/lang/reflect/Module.java --- a/jdk/src/java.base/share/classes/java/lang/reflect/Module.java Wed May 25 17:07:13 2016 +0300 +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Module.java Wed May 25 19:58:03 2016 +0100 @@ -513,7 +513,7 @@ * package {@code pn} to the given module. * *
This method has no effect if the package is already exported to the - * given module. If also has no effect if invoked on an unnamed module (as + * given module. It also has no effect if invoked on an unnamed module (as * unnamed modules export all packages).
* * @param pn @@ -866,7 +866,7 @@ URI uri = mref.location().orElse(null); Module m; - if (loader == null && name.equals("java.base")) { + if (loader == null && name.equals("java.base") && Layer.boot() == null) { m = Object.class.getModule(); } else { m = new Module(layer, loader, descriptor, uri); diff -r bf65323537b2 -r 8c49d605b024 jdk/test/java/lang/reflect/Layer/BasicLayerTest.java --- a/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java Wed May 25 17:07:13 2016 +0300 +++ b/jdk/test/java/lang/reflect/Layer/BasicLayerTest.java Wed May 25 19:58:03 2016 +0100 @@ -103,7 +103,7 @@ /** - * Exercise Layer.create, created on an empty layer + * Exercise Layer defineModules, created with empty layer as parent */ public void testLayerOnEmpty() { ModuleDescriptor descriptor1 @@ -184,7 +184,7 @@ /** - * Exercise Layer.create, created over the boot layer + * Exercise Layer defineModules, created with boot layer as parent */ public void testLayerOnBoot() { ModuleDescriptor descriptor1 @@ -247,8 +247,8 @@ /** - * Layer.create with a configuration of two modules that have the same - * module-private package. + * Exercise Layer defineModules with a configuration of two modules that + * have the same module-private package. */ public void testSameConcealedPackage() { ModuleDescriptor descriptor1 @@ -281,8 +281,8 @@ /** - * Layer.create with a configuration with a partitioned graph. The same - * package is exported in both partitions. + * Exercise Layer defineModules with a configuration that is a partitioned + * graph. The same package is exported in both partitions. */ public void testSameExportInPartitionedGraph() { @@ -338,9 +338,9 @@ /** - * Layer.create with a configuration that contains a module that has a - * concealed package that is the same name as a non-exported package - * in a parent layer. + * Exercise Layer defineModules with a configuration that contains a module + * that has a concealed package that is the same name as a non-exported + * package in a parent layer. */ public void testConcealSamePackageAsBootLayer() { @@ -667,9 +667,9 @@ /** - * Attempt to use Layer.create to create a layer with a module defined to a - * class loader that already has a module of the same name defined to the - * class loader. + * Attempt to use Layer defineModules to create a layer with a module + * defined to a class loader that already has a module of the same name + * defined to the class loader. */ @Test(expectedExceptions = { LayerInstantiationException.class }) public void testModuleAlreadyDefinedToLoader() { @@ -696,9 +696,9 @@ /** - * Attempt to use Layer.create to create a Layer with a module containing - * package {@code p} where the class loader already has a module defined - * to it containing package {@code p}. + * Attempt to use Layer defineModules to create a Layer with a module + * containing package {@code p} where the class loader already has a module + * defined to it containing package {@code p}. */ @Test(expectedExceptions = { LayerInstantiationException.class }) public void testPackageAlreadyInNamedModule() { @@ -738,8 +738,9 @@ /** - * Attempt to use Layer.create to create a Layer with a module containing - * a package in which a type is already loaded by the class loader. + * Attempt to use Layer defineModules to create a Layer with a module + * containing a package in which a type is already loaded by the class + * loader. */ @Test(expectedExceptions = { LayerInstantiationException.class }) public void testPackageAlreadyInUnnamedModule() throws Exception { @@ -763,6 +764,46 @@ /** + * Attempt to create a Layer with a module named "java.base". + */ + public void testLayerWithJavaBase() { + ModuleDescriptor descriptor + = new ModuleDescriptor.Builder("java.base") + .exports("java.lang") + .build(); + + ModuleFinder finder = ModuleUtils.finderOf(descriptor); + + Configuration cf = Layer.boot() + .configuration() + .resolveRequires(finder, ModuleFinder.of(), Set.of("java.base")); + assertTrue(cf.modules().size() == 1); + + ClassLoader scl = ClassLoader.getSystemClassLoader(); + + try { + Layer.boot().defineModules(cf, loader -> null ); + assertTrue(false); + } catch (LayerInstantiationException e) { } + + try { + Layer.boot().defineModules(cf, loader -> new ClassLoader() { }); + assertTrue(false); + } catch (LayerInstantiationException e) { } + + try { + Layer.boot().defineModulesWithOneLoader(cf, scl); + assertTrue(false); + } catch (LayerInstantiationException e) { } + + try { + Layer.boot().defineModulesWithManyLoaders(cf, scl); + assertTrue(false); + } catch (LayerInstantiationException e) { } + } + + + /** * Parent of configuration != configuration of parent Layer */ @Test(expectedExceptions = { IllegalArgumentException.class }) @@ -812,7 +853,6 @@ @Test(expectedExceptions = { NullPointerException.class }) public void testCreateWithNull2() { - ClassLoader loader = new ClassLoader() { }; Configuration cf = resolveRequires(Layer.boot().configuration(), ModuleFinder.of()); Layer.boot().defineModules(cf, null); } diff -r bf65323537b2 -r 8c49d605b024 jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java --- a/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java Wed May 25 17:07:13 2016 +0300 +++ b/jdk/test/java/lang/reflect/Layer/LayerAndLoadersTest.java Wed May 25 19:58:03 2016 +0100 @@ -70,7 +70,7 @@ /** - * Basic test of Layer.defineModulesWithOneLoader + * Basic test of Layer defineModulesWithOneLoader * * Test scenario: * m1 requires m2 and m3 @@ -99,7 +99,7 @@ /** - * Basic test of Layer.defineModulesWithManyLoaders + * Basic test of Layer defineModulesWithManyLoaders * * Test scenario: * m1 requires m2 and m3 @@ -131,7 +131,7 @@ /** - * Basic test of Layer.defineModulesWithOneLoader where one of the modules + * Basic test of Layer defineModulesWithOneLoader where one of the modules * is a service provider module. * * Test scenario: @@ -172,8 +172,8 @@ /** - * Basic test of Layer.defineModulesWithManyLoaders where one of the modules - * is a service provider module. + * Basic test of Layer defineModulesWithManyLoaders where one of the + * modules is a service provider module. * * Test scenario: * m1 requires m2 and m3 @@ -224,7 +224,7 @@ /** - * Tests that the class loaders created by Layer.createWithXXX delegate + * Tests that the class loaders created by defineModulesWithXXX delegate * to the given parent class loader. */ public void testDelegationToParent() throws Exception { @@ -254,7 +254,7 @@ /** - * Test Layer.createWithXXX when modules that have overlapping packages. + * Test defineModulesWithXXX when modules that have overlapping packages. * * Test scenario: * m1 exports p @@ -288,7 +288,7 @@ /** - * Test Layer.createWithXXX with split delegation. + * Test Layer defineModulesWithXXX with split delegation. * * Test scenario: * layer1: m1 exports p, m2 exports p @@ -319,7 +319,8 @@ ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); - Configuration cf2 = cf1.resolveRequires(finder2, ModuleFinder.of(), Set.of("m3", "m4")); + Configuration cf2 = cf1.resolveRequires(finder2, ModuleFinder.of(), + Set.of("m3", "m4")); // package p cannot be supplied by two class loaders try { @@ -335,8 +336,8 @@ /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * Test scenario: * layer1: m1, m2, m3 => same loader @@ -350,7 +351,8 @@ checkLayer(layer1, "m1", "m2", "m3"); ModuleFinder finder = ModuleFinder.of(MODS_DIR); - Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null); checkLayer(layer2, "m1", "m2", "m3"); @@ -383,8 +385,8 @@ /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * Test scenario: * layer1: m1, m2, m3 => loader pool @@ -398,7 +400,8 @@ checkLayer(layer1, "m1", "m2", "m3"); ModuleFinder finder = ModuleFinder.of(MODS_DIR); - Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); checkLayer(layer2, "m1", "m2", "m3"); @@ -477,8 +480,8 @@ /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * layer1: m1, m2, m3 => same loader * layer2: m1, m3 => same loader @@ -492,7 +495,8 @@ ModuleFinder finder = finderFor("m1", "m3"); - Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null); checkLayer(layer2, "m1", "m3"); @@ -513,8 +517,8 @@ /** - * Test Layer.createWithXXX when the modules that override same named - * modules in the parent layer. + * Test Layer defineModulesWithXXX when the modules that override same + * named modules in the parent layer. * * layer1: m1, m2, m3 => loader pool * layer2: m1, m3 => loader pool @@ -528,7 +532,8 @@ ModuleFinder finder = finderFor("m1", "m3"); - Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), Set.of("m1")); + Configuration cf2 = cf1.resolveRequires(finder, ModuleFinder.of(), + Set.of("m1")); Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null); checkLayer(layer2, "m1", "m3");