mirror of
https://github.com/openjdk/jdk.git
synced 2026-07-28 11:53:09 +00:00
8182742: ClassLoader.getResourceXXX throws NPE when ClassLoader created by defineModulesWithXXX
Reviewed-by: redestad, mchung
This commit is contained in:
parent
d26e4ff9b5
commit
7e9984c112
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -28,7 +28,6 @@ package jdk.internal.loader;
|
||||
import java.io.File;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleReader;
|
||||
@ -58,12 +57,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Spliterator;
|
||||
import java.util.Spliterators;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import jdk.internal.misc.SharedSecrets;
|
||||
import jdk.internal.module.Resources;
|
||||
@ -403,12 +398,15 @@ public final class Loader extends SecureClassLoader {
|
||||
|
||||
// this loader
|
||||
URL url = findResource(name);
|
||||
if (url != null) {
|
||||
return url;
|
||||
} else {
|
||||
if (url == null) {
|
||||
// parent loader
|
||||
return parent.getResource(name);
|
||||
if (parent != null) {
|
||||
url = parent.getResource(name);
|
||||
} else {
|
||||
url = BootLoader.findResource(name);
|
||||
}
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -419,7 +417,12 @@ public final class Loader extends SecureClassLoader {
|
||||
List<URL> urls = findResourcesAsList(name);
|
||||
|
||||
// parent loader
|
||||
Enumeration<URL> e = parent.getResources(name);
|
||||
Enumeration<URL> e;
|
||||
if (parent != null) {
|
||||
e = parent.getResources(name);
|
||||
} else {
|
||||
e = BootLoader.findResources(name);
|
||||
}
|
||||
|
||||
// concat the URLs with the URLs returned by the parent
|
||||
return new Enumeration<>() {
|
||||
@ -439,25 +442,6 @@ public final class Loader extends SecureClassLoader {
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<URL> resources(String name) {
|
||||
Objects.requireNonNull(name);
|
||||
// ordering not specified
|
||||
int characteristics = (Spliterator.NONNULL | Spliterator.IMMUTABLE |
|
||||
Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
Supplier<Spliterator<URL>> supplier = () -> {
|
||||
try {
|
||||
List<URL> urls = findResourcesAsList(name);
|
||||
return Spliterators.spliterator(urls, characteristics);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
};
|
||||
Stream<URL> s1 = StreamSupport.stream(supplier, characteristics, false);
|
||||
Stream<URL> s2 = parent.resources(name);
|
||||
return Stream.concat(s1, s2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the resources with the given name in this class loader.
|
||||
*/
|
||||
|
||||
@ -52,6 +52,7 @@ import java.util.Optional;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.test.lib.compiler.CompilerUtils;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
@ -78,7 +79,7 @@ public class LayerAndLoadersTest {
|
||||
* Basic test of ModuleLayer.defineModulesWithOneLoader
|
||||
*
|
||||
* Test scenario:
|
||||
* m1 requires m2 and m3
|
||||
* m1 requires m2 and m3
|
||||
*/
|
||||
public void testWithOneLoader() throws Exception {
|
||||
Configuration cf = resolve("m1");
|
||||
@ -105,7 +106,7 @@ public class LayerAndLoadersTest {
|
||||
* Basic test of ModuleLayer.defineModulesWithManyLoaders
|
||||
*
|
||||
* Test scenario:
|
||||
* m1 requires m2 and m3
|
||||
* m1 requires m2 and m3
|
||||
*/
|
||||
public void testWithManyLoaders() throws Exception {
|
||||
Configuration cf = resolve("m1");
|
||||
@ -136,9 +137,9 @@ public class LayerAndLoadersTest {
|
||||
* modules is a service provider module.
|
||||
*
|
||||
* Test scenario:
|
||||
* m1 requires m2 and m3
|
||||
* m1 uses S
|
||||
* m4 provides S with ...
|
||||
* m1 requires m2 and m3
|
||||
* m1 uses S
|
||||
* m4 provides S with ...
|
||||
*/
|
||||
public void testServicesWithOneLoader() throws Exception {
|
||||
Configuration cf = resolveAndBind("m1");
|
||||
@ -175,9 +176,9 @@ public class LayerAndLoadersTest {
|
||||
* modules is a service provider module.
|
||||
*
|
||||
* Test scenario:
|
||||
* m1 requires m2 and m3
|
||||
* m1 uses S
|
||||
* m4 provides S with ...
|
||||
* m1 requires m2 and m3
|
||||
* m1 uses S
|
||||
* m4 provides S with ...
|
||||
*/
|
||||
public void testServicesWithManyLoaders() throws Exception {
|
||||
Configuration cf = resolveAndBind("m1");
|
||||
@ -234,7 +235,7 @@ public class LayerAndLoadersTest {
|
||||
ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, parent);
|
||||
testLoad(layer, cn);
|
||||
|
||||
// one loader with boot loader as parent
|
||||
// one loader with boot loader as parent
|
||||
layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, null);
|
||||
testLoadFail(layer, cn);
|
||||
|
||||
@ -252,21 +253,21 @@ public class LayerAndLoadersTest {
|
||||
* Test defineModulesWithXXX when modules that have overlapping packages.
|
||||
*
|
||||
* Test scenario:
|
||||
* m1 exports p
|
||||
* m2 exports p
|
||||
* m1 exports p
|
||||
* m2 exports p
|
||||
*/
|
||||
public void testOverlappingPackages() {
|
||||
ModuleDescriptor descriptor1
|
||||
= ModuleDescriptor.newModule("m1").exports("p").build();
|
||||
= ModuleDescriptor.newModule("m1").exports("p").build();
|
||||
|
||||
ModuleDescriptor descriptor2
|
||||
= ModuleDescriptor.newModule("m2").exports("p").build();
|
||||
= ModuleDescriptor.newModule("m2").exports("p").build();
|
||||
|
||||
ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
|
||||
|
||||
Configuration cf = ModuleLayer.boot()
|
||||
.configuration()
|
||||
.resolve(finder, ModuleFinder.of(), Set.of("m1", "m2"));
|
||||
.configuration()
|
||||
.resolve(finder, ModuleFinder.of(), Set.of("m1", "m2"));
|
||||
|
||||
// cannot define both module m1 and m2 to the same class loader
|
||||
try {
|
||||
@ -284,35 +285,35 @@ public class LayerAndLoadersTest {
|
||||
* Test ModuleLayer.defineModulesWithXXX with split delegation.
|
||||
*
|
||||
* Test scenario:
|
||||
* layer1: m1 exports p, m2 exports p
|
||||
* layer2: m3 reads m1, m4 reads m2
|
||||
* layer1: m1 exports p, m2 exports p
|
||||
* layer2: m3 reads m1, m4 reads m2
|
||||
*/
|
||||
public void testSplitDelegation() {
|
||||
ModuleDescriptor descriptor1
|
||||
= ModuleDescriptor.newModule("m1").exports("p").build();
|
||||
= ModuleDescriptor.newModule("m1").exports("p").build();
|
||||
|
||||
ModuleDescriptor descriptor2
|
||||
= ModuleDescriptor.newModule("m2").exports("p").build();
|
||||
= ModuleDescriptor.newModule("m2").exports("p").build();
|
||||
|
||||
ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
|
||||
|
||||
Configuration cf1 = ModuleLayer.boot()
|
||||
.configuration()
|
||||
.resolve(finder1, ModuleFinder.of(), Set.of("m1", "m2"));
|
||||
.configuration()
|
||||
.resolve(finder1, ModuleFinder.of(), Set.of("m1", "m2"));
|
||||
|
||||
ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null);
|
||||
checkLayer(layer1, "m1", "m2");
|
||||
|
||||
ModuleDescriptor descriptor3
|
||||
= ModuleDescriptor.newModule("m3").requires("m1").build();
|
||||
= ModuleDescriptor.newModule("m3").requires("m1").build();
|
||||
|
||||
ModuleDescriptor descriptor4
|
||||
= ModuleDescriptor.newModule("m4").requires("m2").build();
|
||||
= ModuleDescriptor.newModule("m4").requires("m2").build();
|
||||
|
||||
ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
|
||||
|
||||
Configuration cf2 = cf1.resolve(finder2, ModuleFinder.of(),
|
||||
Set.of("m3", "m4"));
|
||||
Set.of("m3", "m4"));
|
||||
|
||||
// package p cannot be supplied by two class loaders
|
||||
try {
|
||||
@ -331,8 +332,8 @@ public class LayerAndLoadersTest {
|
||||
* named modules in the parent layer.
|
||||
*
|
||||
* Test scenario:
|
||||
* layer1: m1, m2, m3 => same loader
|
||||
* layer2: m1, m2, m4 => same loader
|
||||
* layer1: m1, m2, m3 => same loader
|
||||
* layer2: m1, m2, m4 => same loader
|
||||
*/
|
||||
public void testOverriding1() throws Exception {
|
||||
Configuration cf1 = resolve("m1");
|
||||
@ -342,7 +343,7 @@ public class LayerAndLoadersTest {
|
||||
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
|
||||
Set.of("m1"));
|
||||
Set.of("m1"));
|
||||
|
||||
ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
|
||||
checkLayer(layer2, "m1", "m2", "m3");
|
||||
@ -378,8 +379,8 @@ public class LayerAndLoadersTest {
|
||||
* named modules in the parent layer.
|
||||
*
|
||||
* Test scenario:
|
||||
* layer1: m1, m2, m3 => loader pool
|
||||
* layer2: m1, m2, m3 => loader pool
|
||||
* layer1: m1, m2, m3 => loader pool
|
||||
* layer2: m1, m2, m3 => loader pool
|
||||
*/
|
||||
public void testOverriding2() throws Exception {
|
||||
Configuration cf1 = resolve("m1");
|
||||
@ -389,7 +390,7 @@ public class LayerAndLoadersTest {
|
||||
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
|
||||
Set.of("m1"));
|
||||
Set.of("m1"));
|
||||
|
||||
ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
|
||||
checkLayer(layer2, "m1", "m2", "m3");
|
||||
@ -482,7 +483,7 @@ public class LayerAndLoadersTest {
|
||||
ModuleFinder finder = finderFor("m1", "m3");
|
||||
|
||||
Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
|
||||
Set.of("m1"));
|
||||
Set.of("m1"));
|
||||
|
||||
ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
|
||||
checkLayer(layer2, "m1", "m3");
|
||||
@ -517,7 +518,7 @@ public class LayerAndLoadersTest {
|
||||
ModuleFinder finder = finderFor("m1", "m3");
|
||||
|
||||
Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
|
||||
Set.of("m1"));
|
||||
Set.of("m1"));
|
||||
|
||||
ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
|
||||
checkLayer(layer2, "m1", "m3");
|
||||
@ -550,18 +551,27 @@ public class LayerAndLoadersTest {
|
||||
assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Basic test for locating resources with a class loader created by
|
||||
* defineModulesWithOneLoader.
|
||||
*/
|
||||
public void testResourcesWithOneLoader() throws Exception {
|
||||
testResourcesWithOneLoader(ClassLoader.getSystemClassLoader());
|
||||
testResourcesWithOneLoader(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test locating resources with the class loader created by
|
||||
* defineModulesWithOneLoader. The class loader has the given class
|
||||
* loader as its parent.
|
||||
*/
|
||||
void testResourcesWithOneLoader(ClassLoader parent) throws Exception {
|
||||
Configuration cf = resolve("m1");
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl);
|
||||
ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, parent);
|
||||
|
||||
ClassLoader loader = layer.findLoader("m1");
|
||||
assertNotNull(loader);
|
||||
assertTrue(loader.getParent() == parent);
|
||||
|
||||
// check that getResource and getResources are consistent
|
||||
URL url1 = loader.getResource("module-info.class");
|
||||
@ -607,14 +617,24 @@ public class LayerAndLoadersTest {
|
||||
* defineModulesWithManyLoaders.
|
||||
*/
|
||||
public void testResourcesWithManyLoaders() throws Exception {
|
||||
testResourcesWithManyLoaders(ClassLoader.getSystemClassLoader());
|
||||
testResourcesWithManyLoaders(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test locating resources with class loaders created by
|
||||
* defineModulesWithManyLoaders. The class loaders have the given class
|
||||
* loader as their parent.
|
||||
*/
|
||||
void testResourcesWithManyLoaders(ClassLoader parent) throws Exception {
|
||||
Configuration cf = resolve("m1");
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl);
|
||||
ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, parent);
|
||||
|
||||
for (Module m : layer.modules()) {
|
||||
String name = m.getName();
|
||||
ClassLoader loader = m.getClassLoader();
|
||||
assertNotNull(loader);
|
||||
assertTrue(loader.getParent() == parent);
|
||||
|
||||
// getResource should find the module-info.class for the module
|
||||
URL url = loader.getResource("module-info.class");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user