考虑这个(半伪)代码:
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 导入,为什么它需要成为构建路径的一部分才能工作?类加载器根据实际文件使用它,因此它是否与项目的构建路径相关联无关紧要。