8150668: Layer.defineModulesXXX with a Configuration containing java.base throws undocumented exception

Reviewed-by: chegar, mchung
This commit is contained in:
Alan Bateman 2016-05-25 19:58:03 +01:00
parent 600aaed0a7
commit 53e204dc49
4 changed files with 106 additions and 52 deletions

View File

@ -75,11 +75,12 @@ import sun.security.util.SecurityConstants;
* *
* <p> A Java virtual machine has at least one non-empty layer, the {@link * <p> 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 * #boot() boot} layer, that is created when the Java virtual machine is
* started. The <em>system modules</em>, including {@code java.base}, are in * started. The boot layer contains module {@code java.base} and is the only
* the boot layer. The modules in the boot layer are mapped to the bootstrap * layer in the Java virtual machine with a module named "{@code java.base}".
* class loader and other class loaders that are built-in into the Java virtual * The modules in the boot layer are mapped to the bootstrap class loader and
* machine. The boot layer will often be the {@link #parent() parent} when * other class loaders that are <a href="../ClassLoader.html#builtinLoaders">
* creating additional layers. </p> * built-in</a> into the Java virtual machine. The boot layer will often be
* the {@link #parent() parent} when creating additional layers. </p>
* *
* <p> As when creating a {@code Configuration}, * <p> As when creating a {@code Configuration},
* {@link ModuleDescriptor#isAutomatic() automatic} modules receive * {@link ModuleDescriptor#isAutomatic() automatic} modules receive
@ -204,7 +205,8 @@ public final class Layer {
* for this layer * for this layer
* @throws LayerInstantiationException * @throws LayerInstantiationException
* If all modules cannot be defined to the same class loader for any * 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 * @throws SecurityException
* If {@code RuntimePermission("createClassLoader")} or * If {@code RuntimePermission("createClassLoader")} or
* {@code RuntimePermission("getClassLoader")} is denied by * {@code RuntimePermission("getClassLoader")} is denied by
@ -219,14 +221,13 @@ public final class Layer {
checkCreateClassLoaderPermission(); checkCreateClassLoaderPermission();
checkGetClassLoaderPermission(); checkGetClassLoaderPermission();
Loader loader;
try { try {
loader = new Loader(cf.modules(), parentLoader); Loader loader = new Loader(cf.modules(), parentLoader);
loader.initRemotePackageMap(cf, this); loader.initRemotePackageMap(cf, this);
return new Layer(cf, this, mn -> loader);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
throw new LayerInstantiationException(e.getMessage()); throw new LayerInstantiationException(e.getMessage());
} }
return new Layer(cf, this, mn -> loader);
} }
@ -266,6 +267,9 @@ public final class Layer {
* @throws IllegalArgumentException * @throws IllegalArgumentException
* If the parent of the given configuration is not the configuration * If the parent of the given configuration is not the configuration
* for this layer * for this layer
* @throws LayerInstantiationException
* If the layer cannot be created because the configuration contains
* a module named "{@code java.base}"
* @throws SecurityException * @throws SecurityException
* If {@code RuntimePermission("createClassLoader")} or * If {@code RuntimePermission("createClassLoader")} or
* {@code RuntimePermission("getClassLoader")} is denied by * {@code RuntimePermission("getClassLoader")} is denied by
@ -281,7 +285,11 @@ public final class Layer {
checkGetClassLoaderPermission(); checkGetClassLoaderPermission();
LoaderPool pool = new LoaderPool(cf, this, parentLoader); 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 @@ public final class Layer {
* for this layer * for this layer
* @throws LayerInstantiationException * @throws LayerInstantiationException
* If creating the {@code Layer} fails for any of the reasons * 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 * @throws SecurityException
* If {@code RuntimePermission("getClassLoader")} is denied by * If {@code RuntimePermission("getClassLoader")} is denied by
* the security manager * the security manager

View File

@ -513,7 +513,7 @@ public final class Module {
* package {@code pn} to the given module. * package {@code pn} to the given module.
* *
* <p> This method has no effect if the package is already exported to the * <p> 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). </p> * unnamed modules export all packages). </p>
* *
* @param pn * @param pn
@ -866,7 +866,7 @@ public final class Module {
URI uri = mref.location().orElse(null); URI uri = mref.location().orElse(null);
Module m; Module m;
if (loader == null && name.equals("java.base")) { if (loader == null && name.equals("java.base") && Layer.boot() == null) {
m = Object.class.getModule(); m = Object.class.getModule();
} else { } else {
m = new Module(layer, loader, descriptor, uri); m = new Module(layer, loader, descriptor, uri);

View File

@ -103,7 +103,7 @@ public class BasicLayerTest {
/** /**
* Exercise Layer.create, created on an empty layer * Exercise Layer defineModules, created with empty layer as parent
*/ */
public void testLayerOnEmpty() { public void testLayerOnEmpty() {
ModuleDescriptor descriptor1 ModuleDescriptor descriptor1
@ -184,7 +184,7 @@ public class BasicLayerTest {
/** /**
* Exercise Layer.create, created over the boot layer * Exercise Layer defineModules, created with boot layer as parent
*/ */
public void testLayerOnBoot() { public void testLayerOnBoot() {
ModuleDescriptor descriptor1 ModuleDescriptor descriptor1
@ -247,8 +247,8 @@ public class BasicLayerTest {
/** /**
* Layer.create with a configuration of two modules that have the same * Exercise Layer defineModules with a configuration of two modules that
* module-private package. * have the same module-private package.
*/ */
public void testSameConcealedPackage() { public void testSameConcealedPackage() {
ModuleDescriptor descriptor1 ModuleDescriptor descriptor1
@ -281,8 +281,8 @@ public class BasicLayerTest {
/** /**
* Layer.create with a configuration with a partitioned graph. The same * Exercise Layer defineModules with a configuration that is a partitioned
* package is exported in both partitions. * graph. The same package is exported in both partitions.
*/ */
public void testSameExportInPartitionedGraph() { public void testSameExportInPartitionedGraph() {
@ -338,9 +338,9 @@ public class BasicLayerTest {
/** /**
* Layer.create with a configuration that contains a module that has a * Exercise Layer defineModules with a configuration that contains a module
* concealed package that is the same name as a non-exported package * that has a concealed package that is the same name as a non-exported
* in a parent layer. * package in a parent layer.
*/ */
public void testConcealSamePackageAsBootLayer() { public void testConcealSamePackageAsBootLayer() {
@ -667,9 +667,9 @@ public class BasicLayerTest {
/** /**
* Attempt to use Layer.create to create a layer with a module defined to a * Attempt to use Layer defineModules to create a layer with a module
* class loader that already has a module of the same name defined to the * defined to a class loader that already has a module of the same name
* class loader. * defined to the class loader.
*/ */
@Test(expectedExceptions = { LayerInstantiationException.class }) @Test(expectedExceptions = { LayerInstantiationException.class })
public void testModuleAlreadyDefinedToLoader() { public void testModuleAlreadyDefinedToLoader() {
@ -696,9 +696,9 @@ public class BasicLayerTest {
/** /**
* Attempt to use Layer.create to create a Layer with a module containing * Attempt to use Layer defineModules to create a Layer with a module
* package {@code p} where the class loader already has a module defined * containing package {@code p} where the class loader already has a module
* to it containing package {@code p}. * defined to it containing package {@code p}.
*/ */
@Test(expectedExceptions = { LayerInstantiationException.class }) @Test(expectedExceptions = { LayerInstantiationException.class })
public void testPackageAlreadyInNamedModule() { public void testPackageAlreadyInNamedModule() {
@ -738,8 +738,9 @@ public class BasicLayerTest {
/** /**
* Attempt to use Layer.create to create a Layer with a module containing * Attempt to use Layer defineModules to create a Layer with a module
* a package in which a type is already loaded by the class loader. * containing a package in which a type is already loaded by the class
* loader.
*/ */
@Test(expectedExceptions = { LayerInstantiationException.class }) @Test(expectedExceptions = { LayerInstantiationException.class })
public void testPackageAlreadyInUnnamedModule() throws Exception { public void testPackageAlreadyInUnnamedModule() throws Exception {
@ -762,6 +763,46 @@ public class BasicLayerTest {
} }
/**
* 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 * Parent of configuration != configuration of parent Layer
*/ */
@ -812,7 +853,6 @@ public class BasicLayerTest {
@Test(expectedExceptions = { NullPointerException.class }) @Test(expectedExceptions = { NullPointerException.class })
public void testCreateWithNull2() { public void testCreateWithNull2() {
ClassLoader loader = new ClassLoader() { };
Configuration cf = resolveRequires(Layer.boot().configuration(), ModuleFinder.of()); Configuration cf = resolveRequires(Layer.boot().configuration(), ModuleFinder.of());
Layer.boot().defineModules(cf, null); Layer.boot().defineModules(cf, null);
} }

View File

@ -70,7 +70,7 @@ public class LayerAndLoadersTest {
/** /**
* Basic test of Layer.defineModulesWithOneLoader * Basic test of Layer defineModulesWithOneLoader
* *
* Test scenario: * Test scenario:
* m1 requires m2 and m3 * m1 requires m2 and m3
@ -99,7 +99,7 @@ public class LayerAndLoadersTest {
/** /**
* Basic test of Layer.defineModulesWithManyLoaders * Basic test of Layer defineModulesWithManyLoaders
* *
* Test scenario: * Test scenario:
* m1 requires m2 and m3 * m1 requires m2 and m3
@ -131,7 +131,7 @@ public class LayerAndLoadersTest {
/** /**
* 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. * is a service provider module.
* *
* Test scenario: * Test scenario:
@ -172,8 +172,8 @@ public class LayerAndLoadersTest {
/** /**
* Basic test of Layer.defineModulesWithManyLoaders where one of the modules * Basic test of Layer defineModulesWithManyLoaders where one of the
* is a service provider module. * modules is a service provider module.
* *
* Test scenario: * Test scenario:
* m1 requires m2 and m3 * m1 requires m2 and m3
@ -224,7 +224,7 @@ public class LayerAndLoadersTest {
/** /**
* 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. * to the given parent class loader.
*/ */
public void testDelegationToParent() throws Exception { public void testDelegationToParent() throws Exception {
@ -254,7 +254,7 @@ public class LayerAndLoadersTest {
/** /**
* Test Layer.createWithXXX when modules that have overlapping packages. * Test defineModulesWithXXX when modules that have overlapping packages.
* *
* Test scenario: * Test scenario:
* m1 exports p * m1 exports p
@ -288,7 +288,7 @@ public class LayerAndLoadersTest {
/** /**
* Test Layer.createWithXXX with split delegation. * Test Layer defineModulesWithXXX with split delegation.
* *
* Test scenario: * Test scenario:
* layer1: m1 exports p, m2 exports p * layer1: m1 exports p, m2 exports p
@ -319,7 +319,8 @@ public class LayerAndLoadersTest {
ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); 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 // package p cannot be supplied by two class loaders
try { try {
@ -335,8 +336,8 @@ public class LayerAndLoadersTest {
/** /**
* Test Layer.createWithXXX when the modules that override same named * Test Layer defineModulesWithXXX when the modules that override same
* modules in the parent layer. * named modules in the parent layer.
* *
* Test scenario: * Test scenario:
* layer1: m1, m2, m3 => same loader * layer1: m1, m2, m3 => same loader
@ -350,7 +351,8 @@ public class LayerAndLoadersTest {
checkLayer(layer1, "m1", "m2", "m3"); checkLayer(layer1, "m1", "m2", "m3");
ModuleFinder finder = ModuleFinder.of(MODS_DIR); 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); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
checkLayer(layer2, "m1", "m2", "m3"); checkLayer(layer2, "m1", "m2", "m3");
@ -383,8 +385,8 @@ public class LayerAndLoadersTest {
/** /**
* Test Layer.createWithXXX when the modules that override same named * Test Layer defineModulesWithXXX when the modules that override same
* modules in the parent layer. * named modules in the parent layer.
* *
* Test scenario: * Test scenario:
* layer1: m1, m2, m3 => loader pool * layer1: m1, m2, m3 => loader pool
@ -398,7 +400,8 @@ public class LayerAndLoadersTest {
checkLayer(layer1, "m1", "m2", "m3"); checkLayer(layer1, "m1", "m2", "m3");
ModuleFinder finder = ModuleFinder.of(MODS_DIR); 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); Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
checkLayer(layer2, "m1", "m2", "m3"); checkLayer(layer2, "m1", "m2", "m3");
@ -477,8 +480,8 @@ public class LayerAndLoadersTest {
/** /**
* Test Layer.createWithXXX when the modules that override same named * Test Layer defineModulesWithXXX when the modules that override same
* modules in the parent layer. * named modules in the parent layer.
* *
* layer1: m1, m2, m3 => same loader * layer1: m1, m2, m3 => same loader
* layer2: m1, m3 => same loader * layer2: m1, m3 => same loader
@ -492,7 +495,8 @@ public class LayerAndLoadersTest {
ModuleFinder finder = finderFor("m1", "m3"); 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); Layer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
checkLayer(layer2, "m1", "m3"); checkLayer(layer2, "m1", "m3");
@ -513,8 +517,8 @@ public class LayerAndLoadersTest {
/** /**
* Test Layer.createWithXXX when the modules that override same named * Test Layer defineModulesWithXXX when the modules that override same
* modules in the parent layer. * named modules in the parent layer.
* *
* layer1: m1, m2, m3 => loader pool * layer1: m1, m2, m3 => loader pool
* layer2: m1, m3 => loader pool * layer2: m1, m3 => loader pool
@ -528,7 +532,8 @@ public class LayerAndLoadersTest {
ModuleFinder finder = finderFor("m1", "m3"); 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); Layer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
checkLayer(layer2, "m1", "m3"); checkLayer(layer2, "m1", "m3");