Martin Tuskevicius
Martin Tuskevicius

Reputation: 2630

Why does a library need to be part of the build path if nothing is imported from it?

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:

First project setup. Second project setup.

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:

Order and Export list.

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

Answers (1)

Patricia Shanahan
Patricia Shanahan

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

Related Questions