Skip to content

Commit bbf1ff4

Browse files
authored
Allow ModuleClassLoader to optionally delegate class-loading to parent (#60)
1 parent fd3fa25 commit bbf1ff4

File tree

1 file changed

+23
-2
lines changed

1 file changed

+23
-2
lines changed

src/main/java/cpw/mods/cl/ModuleClassLoader.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package cpw.mods.cl;
22

33
import cpw.mods.util.LambdaExceptionUtils;
4+
import org.jetbrains.annotations.Nullable;
5+
import org.jetbrains.annotations.VisibleForTesting;
46

57
import java.io.IOException;
68
import java.io.InputStream;
@@ -64,10 +66,29 @@ private static void bindToLayer(ModuleClassLoader classLoader, ModuleLayer layer
6466
private final Map<String, JarModuleFinder.JarModuleReference> resolvedRoots;
6567
private final Map<String, ResolvedModule> packageLookup;
6668
private final Map<String, ClassLoader> parentLoaders;
67-
private ClassLoader fallbackClassLoader = ClassLoader.getPlatformClassLoader();
69+
private ClassLoader fallbackClassLoader;
6870

6971
public ModuleClassLoader(final String name, final Configuration configuration, final List<ModuleLayer> parentLayers) {
70-
super(name, null);
72+
this(name, configuration, parentLayers, null);
73+
}
74+
75+
/**
76+
* This constructor allows setting the parent {@linkplain ClassLoader classloader}. Use this with caution since
77+
* it will allow loading of classes from the classpath directly if the {@linkplain ClassLoader#getSystemClassLoader() system classloader}
78+
* is reachable from the given parent classloader.
79+
* <p>
80+
* Generally classes that are in packages covered by reachable modules are preferably loaded from these modules.
81+
* If a class-path entry is not shadowed by a module, specifying a parent class-loader may lead to those
82+
* classes now being loadable instead of throwing a {@link ClassNotFoundException}.
83+
* <p>
84+
* This relaxed classloader isolation is used in unit-testing, where testing libraries are loaded on the
85+
* system class-loader outside our control (by the Gradle test runner). We must not reload these classes
86+
* inside the module layers again, otherwise tests throw incompatible exceptions or may not be found at all.
87+
*/
88+
@VisibleForTesting
89+
public ModuleClassLoader(final String name, final Configuration configuration, final List<ModuleLayer> parentLayers, @Nullable ClassLoader parentLoader) {
90+
super(name, parentLoader);
91+
this.fallbackClassLoader = Objects.requireNonNullElse(parentLoader, ClassLoader.getPlatformClassLoader());
7192
this.configuration = configuration;
7293
this.packageLookup = new HashMap<>();
7394
this.resolvedRoots = configuration.modules().stream()

0 commit comments

Comments
 (0)