I'm trying to make a URLClassLoader which behaves as follows:
- If asked for a class whose name is in a given set of inclusions, load it as normal
- Otherwise, return a dummy class
I can't get this to work. In the attempt below, I expect the SpecialClassLoader
to load Test$Thing
succesfully. In doing so, I expect it to attempt to load Test$SuperThing
, and I expect it to be okay about the fact that the dummy class Nothing
is loaded instead.
However, something goes awry and a NoClassDefFoundError
is thrown looking for Test$SuperThing
.
Does anyone know how to fix this?
public class Test {
private static class SuperThing {}
private static class Thing extends SuperThing {}
public static void main(String[] args) {
Set<String> inclusions = new HashSet<String>();
inclusions.add("Test$Thing"); // note Test$SuperThing is excluded
URLClassLoader cl = (URLClassLoader)
Thread.currentThread().getContextClassLoader();
SpecialClassLoader cll =
new SpecialClassLoader(cl.getURLs(), inclusions);
try {
cll.loadClass("Test$Thing"); // line 22 (see stacktrace below)
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
private static class Nothing {}
private static final class SpecialClassLoader extends URLClassLoader {
private final Set<String> inclusions;
public SpecialClassLoader(URL[] urls, Set<String> inclusions) {
super(urls);
this.inclusions = inclusions;
}
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
if (inclusions.contains(name)) {
return findClass(name); // line 40 (see stacktrace below)
}
return Nothing.class;
}
}
}
EDIT: here is the stacktrace I get (line numbers 22 and 40 are indicated in listing above):
Exception in thread "main" java.lang.NoClassDefFoundError: Test$SuperThing at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$000(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at Test$SpecialClassLoader.loadClass(Test.java:40) at Test.main(Test.java:22)