我有以下Java代码片段:
final Class<?> junitCoreClass = AccessController.doPrivileged(
new PrivilegedAction<URLClassLoader>() {
@Override
public URLClassLoader run() {
return new URLClassLoader(new URL[] { junitJarUrl });
}
}).loadClass("org.junit.runner.JUnitCore");
System.out.println(junitCoreClass.getName());
final JUnitCore junitCore = (JUnitCore) junitCoreClass.newInstance();
编译好。但是当我试图运行它时,会发生一些奇怪的事情;最后一行抛出java.lang.NoClassDefFoundError
,引用刚刚加载的类。奇怪的是,println
打印出确切的类名。
我检查过如果我将新实例引用保留为Object
并仅通过反射操作它,一切都很好,所以违规代码必须是显式转换。
有人可以向我解释为什么会发生这种情况,并告诉我如何实现我想要做的事情?
PS:对于那些想要查看更接近堆栈跟踪的人来说,没有太多要显示的内容:
java.lang.NoClassDefFoundError: org/junit/runner/JUnitCore at [last line of example) [lines from my app] Caused by: java.lang.ClassNotFoundException: org.junit.runner.JUnitCore at java.net.URLClassLoader$1.run(URLClassLoader.java:200) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:315) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:330) at java.lang.ClassLoader.loadClass(ClassLoader.java:250) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:398) at [last line of example] [lines from my app]
答案 0 :(得分:4)
问题是你的主类是由类路径上没有JUnit的系统类加载器(包含-classpath的加载器)加载的。然后,您创建一个单独的类加载器,在类路径上只有JUnit。当您的主类尝试强制转换为JUnitCore时,系统类加载器会被要求加载它不包含的JUnitCore,因此会发生NoClassDefFoundError。
如果不使用反射,就没有方便的方法来做你想做的事情。您需要(1)创建一个直接访问JUnitCore的单独类,(2)在URLClassLoader(目录或JAR)上包含该类的路径,(3)使用反射来加载该类,以及(4)使用反射来在该类上调用一个方法。
答案 1 :(得分:-1)
您是否需要执行.loadClass("org.junit.runner.JUnitCore", **true**);
或者在创建新实例之前在类对象上调用resolveClass()?