运行包含jar jar的jar时,Java NoClassDefFoundError

时间:2012-10-01 06:31:20

标签: java ant classpath

几个小时后,即使在阅读了大量的文档和SO问题之后,我仍然在机智的尽头。我确信我错过了一些明显的东西,但我无法弄明白。

我创建了许多java文件,包括带有main方法的单个入口点。该类还在jar文件mylib.jar中使用位于com.test.lib.MyLibraryClass.class中的一个“库”类。我正在使用以下ant XML成功构建 my jar文件。

<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>

当我检查通过执行该目标而创建的jar时,我发现它确实包含了我的所有.class文件以及mylib.jar。

但是当我尝试运行jar时,我收到以下错误:

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

我需要改变什么?我是否会生成格式错误或不完整的清单?

非常感谢你!

2 个答案:

答案 0 :(得分:4)

问题是标准类加载器找不到位于另一个JAR中的JAR中的类。 Class-Path清单变量实际告诉JVM将当前目录中的mylib.jar文件添加到类路径中。

有三种解决方案:

  • mylib.jar文件放在可以找到的位置(并相应地设置清单属性。

  • 创建一个Uber-jar,它将主JAR中的类和所有相关的库JAR组合成一个JAR文件。

  • 编写一个时髦的类加载器,它知道如何从JAR-in-a-JAR加载,并修改应用程序以实例化并使用类加载器。 (不推荐这种方法......)

请注意,前两个选项通过以不同方式摆脱JAR-in-a-JAR结构来解决问题。

答案 1 :(得分:2)

如果您尝试使用java命令运行它,则不支持在jar中嵌入jar。通过清单中的该条目,类加载器将在您从中启动类的基础文件夹中查找jar,而不是在Jar中。您可以将mylib.jar放在基本文件夹中并使用-cp mylib.jar`选项运行java,也可以使用支持运行嵌入式jar的jar的任何工具。看看this或只是jar&#39;中的Google&#39; jars,你会得到大量的点击。