Reputation: 2630
Consider this (semi-pseudo) code:
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();
}
}
... and these two project setups in the Eclipse IDE:
The provided code does not import anything from the JAR file, yet the behavior is different. How is it different? Well for one, an error is thrown in the theme of this website when using the first project setup:
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)
The error occurring at the line:
mainMethod.invoke(null, (Object) new String[] { "-arguments" });
However, the error does not occur when using the second project setup (the one in which the JAR is part of the build path). Along with that, the code simply does not work when using the first project setup. I know what should happen when it works correctly, and it does not happen with the first project setup, but it does with the second. Another thing worthy of mention is that the code will only work if the the JAR file is at the top of the list of Order and Exports in Eclipse:
Why does that happen? If nothing is imported from the JAR, why does it need to be part of the build path to work? The class loader uses it based on the actual file, so it should not matter if it is associated with the project's build path.
Upvotes: 2
Views: 88
Reputation: 26185
StackOverflowError generally means a call loop. In this case, I think the JVM may be thrashing around looking for something it needs, for example to check whether a class it is trying to link is valid.
Linking is needed in order to run a method, and involves verification, and resolution of symbolic references.
To further understand what is going wrong without the library it would be necessary to see the code for the main class to know what it references.
Do not attach too much significance to import in Java. It just allows you to use class names without fully qualifying them: ArrayList, rather than java.util.ArrayList.
Upvotes: 3