Steve Freeland - 2008-07-24

Hi,

I'm trying to run a project that depends on the jxl library, nested into a top-level jar using OneJar.  I'm running into some odd problems, namely:

d:/dev/j2se/v1_6_0_01/bin/java.exe -Done-jar.verbose=true -jar jar/bb2xls.jar
JarClassLoader: Info: resource: jar\bb2xls.jar!/META-INF/MANIFEST.MF
JarClassLoader: cached bytes for class DirectoryIterator.class
JarClassLoader: cached bytes for class DirectoryIteratorNode.class
[ snip ]
JarClassLoader: Info: caching lib/jxl.jar
JarClassLoader: using jarFile.getInputStream(lib/jxl.jar)
JarClassLoader: cached bytes for class jxl.WorkbookSettings.class
[ snip ]
JarClassLoader: cached bytes for class jxl.write.WritableCell.class
[ snip ]
Exception in thread "main" java.lang.NoClassDefFoundError: jxl/write/WritableCell
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2427)
        at java.lang.Class.getMethod0(Class.java:2670)
        at java.lang.Class.getMethod(Class.java:1603)
        at com.simontuffs.onejar.Boot.run(Boot.java:305)
        at com.simontuffs.onejar.Boot.main(Boot.java:159)

Running under a debugger, I have confirmed that the Boot class is being initialized properly and then loads the "final" main class, namely bb2xls.  It fails when attempting to get the main(String[]) method from bb2xls.  The method is present; the failure seems to occur when pulling in the class' dependancies from the nested jar.

The debugger also revealed that the exception is actually being thrown deeper in the stack.  The following is above java.lang.Class.getDeclaredMethods0() on the stack:
URLClassLoader$1.run:200
AccessController.doPrivileged
URLClassLoader.findClass:188
ClassLoader.loadClass:306
Launcher$AppClassLoader.loadClass:276
ClassLoader.loadClass:251
ClassLoader.loadClassInternal:319

The problem seems to be that the ClassLoader instance called by getDeclaredMethods0() is the default URLClassLoader and not the JarClassLoader created in Boot.  I have no idea why this would be, though, and since getDeclaredMethods0() is native I'm not sure how to find out.

Any ideas on this?
Thanks,
- Steve