运行包含库jar的jar文件时出现Java NoClassDefFoundError错误

3
几个小时后,尽管我已经阅读了大量文档和stackoverflow问题,但我已经无计可施。 我确定我错过了一些显而易见的东西,但我就是想不出来。
我创建了许多Java文件,包括一个带有主方法的单入口点类。该类还使用了一个“库”类,该类位于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个回答

4
问题在于标准类加载器无法找到嵌套在另一个JAR文件中的类。实际上,Class-Path清单变量告诉JVM将当前目录中的mylib.jar文件添加到类路径中。
有三种解决方案:
  • mylib.jar文件放在可以找到的地方(并相应设置清单属性)。

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

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

请注意,前两个替代方案通过不同的方式消除了JAR-in-a-JAR结构的问题。

@Walker 在执行jar文件时,您可以使用java -cp jarfile jartoexecute命令来执行它,这应该可以正常工作。 - thar45
1
@Stranger - 但这并没有直接解决JAR in a JAR的问题。 - Stephen C

2
如果您尝试使用`java`命令运行它,则不支持在jar包中嵌入其他jar包。有了清单中的该条目,类加载器将在启动类所在的基础文件夹中查找jar包,而不是在Jar包内部查找。您可以将`mylib.jar`放在基础文件夹中并使用`-cp mylib.jar`选项运行`java`,或者使用任何支持在嵌入式jar包中运行的工具。请参阅此文或搜索“jars within jar”,您将获得大量结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接