考虑这个(半伪)代码:
private static final File file = new File("./archive.jar");
private static URLClassLoader classLoader;
public static void main(final String[] args) {
try {
classLoader = new URLClassLoader(new URL[] { file.toURI().toURL() });
Method mainMethod = classLoader.loadClass("main class").getDeclaredMethod("main", String[].class);
mainMethod.setAccessible(true);
mainMethod.invoke(null, (Object) new String[] { "-arguments" });
} catch(Exception e) {
e.printStackTrace();
}
}
...以及Eclipse IDE中的这两个项目设置:
提供的代码不会从JAR文件导入任何内容,但行为却不同。它有什么不同?好吧,在使用第一个项目设置时,在本网站的主题中会出现错误:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
Caused by: java.lang.StackOverflowError
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
该行发生错误:
mainMethod.invoke(null, (Object) new String[] { "-arguments" });
但是,使用第二个项目设置(JAR是构建路径的一部分)时,不会发生错误。除此之外,使用第一个项目设置时代码根本不起作用。我知道当它正常工作时会发生什么,并且第一个项目设置不会发生,但它与第二个项目设置不同。值得一提的另一件事是代码只有在JAR文件位于Eclipse中Order和Exports列表的顶部时才有效:
为什么会这样?如果没有从JAR导入任何内容,为什么它需要成为构建路径的一部分才能工作?类加载器根据实际文件使用它,因此它与项目的构建路径相关联无关紧要。
答案 0 :(得分:3)
StackOverflowError通常表示调用循环。在这种情况下,我认为JVM可能正在寻找它需要的东西,例如检查它试图链接的类是否有效。
需要链接才能运行方法,并涉及验证和符号引用的解析。
为了进一步了解没有库的问题,有必要查看主类的代码以了解它所引用的内容。
不要在Java中导入过多的意义。它只允许你使用类名而不完全限定它们:ArrayList,而不是java.util.ArrayList。