この(半疑似)コードを考えてみましょう:
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 での次の 2 つのプロジェクト設定:
提供されたコードは JAR ファイルから何もインポートしませんが、動作は異なります。どう違うの?まず、最初のプロジェクト設定を使用すると、この Web サイトのテーマでエラーがスローされます。
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" });
ただし、2 番目のプロジェクト セットアップ (JAR がビルド パスの一部であるプロジェクト) を使用すると、エラーは発生しません。それに加えて、最初のプロジェクト設定を使用すると、コードが機能しません。正しく動作する場合に何が起こるかはわかっています。最初のプロジェクトのセットアップでは発生しませんが、2 番目のプロジェクトでは発生します。言及する価値のあるもう 1 つのことは、JAR ファイルが Eclipse の Order and Exports のリストの一番上にある場合にのみ、コードが機能することです。
なぜそれが起こるのですか?JAR から何もインポートされていない場合、ビルド パスの一部である必要があるのはなぜですか? クラス ローダーは実際のファイルに基づいてこれを使用するため、プロジェクトのビルド パスに関連付けられているかどうかは問題ではありません。