Strange noclassdefnotfounderror with custom classloader
I know the complexities of classloading are difficult and I probably
need more logic here.
My goal was to have one jar and then have a user double click on the
jar in windows and have logic to load all the other dependent jars
using java code, custom loader. I had several reasons to do this.
There are several other jars and you can see the list here:
public static final String [] JAVA_LIBRARIES = {
"lib\\log4j-1.2.15.jar",
"lib\\octane_commons.jar",
"lib\\clojure.jar",
"lib\\swt\\win32\\swt.jar",
"lib\\jfreechart\\jcommon-1.0.15.jar",
"lib\\jfreechart\\jfreechart-1.0.12.jar",
"lib\\jfreechart\\jfreechart-1.0.12-swt.jar",
"lib\\pdf\\minium.jar",
"lib\\pdf\\tagsoup-1.2.jar",
"lib\\pdf\\core-renderer.jar",
"lib",
"conf",
"src"
};
My classloader code is based on jetty's classloader and it works OK
but I keep get ting classnotdef errors. Strange ones. I can see a
clear distinction between classnotfound errors. If the file path to
the jar is invalid then I get classnotfound, easy to detect and fix.
Here is essentially the classloader code for future reference.
Classpath classpath = new Classpath();
boolean res = classpath.addComponent(libFilePath);
/// Classloader
private class Loader extends URLClassLoader {
String name;
Loader(URL[] urls, ClassLoader parent) {
super(urls, parent);
name = "StartLoader" + Arrays.asList(urls);
}
public String toString() {
return name;
}
}
//// Then set the classloader
//// where the URLs are the JAR libraries:
URL [] urls = new URL[NUMBER_OF_JARS];
for (x in urls) {
urls[i] = new URL("THE JAR PATH");
}
ClassLoader parent = Thread.currentThread().getContextClassLoader
();
if (parent == null) {
parent = Classpath.class.getClassLoader();
}
if (parent == null) {
parent = ClassLoader.getSystemClassLoader();
}
return new Loader(urls, parent);
/////////////
The code works fine but I can't explain for when I get classpath
loader issues. I have one theory one issue.
[java] Exception in thread "main" java.lang.NoClassDefFoundError:
clojure/l
ng/IFn
[java] at java.lang.ClassLoader.defineClass1(Native Method)
[java] at java.lang.ClassLoader.defineClass(ClassLoader.java:
620)
[java] at java.security.SecureClassLoader.defineClass
(SecureClassLoader
java:124)
[java] at java.net.URLClassLoader.defineClass
(URLClassLoader.java:260)
[java] at java.net.URLClassLoader.access$100
(URLClassLoader.java:56)
[java] at java.net.URLClassLoader$1.run(URLClassLoader.java:
195)
[java] at java.security.AccessController.doPrivileged(Native
Method)
[java] at java.net.URLClassLoader.findClass
(URLClassLoader.java:188)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:
306)
[java] at sun.misc.Launcher$AppClassLoader.loadClass
(Launcher.java:268)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:
299)
[java] at java.lang.ClassLoader.loadClass(ClassLoader.java:
251)
[java] at java.lang.ClassLoader.loadClassInternal
(ClassLoader.java:319)
[java] at java.lang.Class.getDeclaredFields0(Native Method)
[java] at java.lang.Class.privateGetDeclaredFields(Class.java:
2259)
[java] at java.lang.Class.getDeclaredField(Class.java:1852)
I believe I Get this errror because there are multiple "classes" on
the same name in the classpath from two different jars and I guess the
classloader is confused?
other than that, i get other errors as well but can't pinpoint how I
get them.
Do you know how to diagnose these problems, should I build a more
robust classloader.