Java NoClassDefFoundError when running jar containing library jar

北战南征 提交于 2019-12-23 15:35:30

问题


After several hours, I'm at my wit's end, even after reading reams of documentation and SO questions. I'm certain that I'm missing something obvious, but I just can't figure it out.

I've created a number of java files, including a single entry point with a main method. That class also makes use of one "library" class, located in com.test.lib.MyLibraryClass.class, within a jar file, mylib.jar. I'm building my jar file successfully using the following ant XML.

<target name="jar" depends="compile">
        <jar destfile="${jar.dir}/${jar.name}.jar">
            <fileset dir="${classes.dir}" />
            <fileset dir="${lib.dir}" />
            <manifest>
                <attribute name="Main-Class" value="${main-class}" />
                <attribute name="Class-Path" value="mylib.jar"/>
            </manifest>
        </jar>
    </target>

When I inspect the jar created by executing that target, I see that it does contain all of my .class files as well as mylib.jar.

When I try to run the jar however, I get the following error:

Exception in thread "main" java.lang.NoClassDefFoundError: com/test/lib/MyLibraryClass
    at com.mytest.MyMain.<init>(Unknown Source)
    at com.mytest.MyMain.main(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.test.lib.MyLibraryClass
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    ... 2 more

What do I need to change? Am I generating a malformed or incomplete manifest?

Thank you so much!


回答1:


The problem is that the standard classloader cannot find classes that are in a JAR that is inside another JAR. The Class-Path manifest variable is actually telling the JVM to add the mylib.jar file in the current directory to the classpath.

There are three solutions:

  • Put the mylib.jar file somewhere that it can be found (and set the manifest property accordingly.

  • Create an Uber-jar that combines the classes in your main JAR and all of the relevant library JARs into one JAR file.

  • Write a funky class loader that knows how to load from a JAR-in-a-JAR, and modify the application to instantiate and use the classloader. (This approach is NOT recommended ...)

Note that the first two alternatives solve the problem by getting rid of your JAR-in-a-JAR structure ... in different ways.




回答2:


If you're trying to run it with the java command, this does not support embedding jars within a jar. With that entry in the manifest the class loader is going to look for the jar in the base folder from where you're launching the class, not inside the Jar. You can either put mylib.jar in your base folder and run java with the -cp mylib.jar` option, or use any of the tools out there that support running jars with embedded jars. Take a look at this or just Google 'jars within jar', you'll get tons of hits.



来源:https://stackoverflow.com/questions/12668454/java-noclassdeffounderror-when-running-jar-containing-library-jar

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!