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)