3

几个小时后,即使在阅读了大量文档和 SO 问题之后,我也束手无策。我确定我遗漏了一些明显的东西,但我就是想不通。

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

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

非常感谢!

4

2 回答 2

4

问题是标准类加载器无法找到在另一个 JAR 中的 JAR 中的类。Class-Pathmanifest 变量实际上是告诉 JVM 将当前目录中的文件添加到mylib.jar类路径中。

有三种解决方案:

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

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

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

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

于 2012-10-01T06:46:57.917 回答
2

如果您尝试使用该java命令运行它,则不支持在 jar 中嵌入 jar。使用清单中的该条目,类加载器将在您启动类的基本文件夹中查找 jar,而不是在 Jar 中。您可以放入mylib.jar基本文件夹并java使用 -cp mylib.jar` 选项运行,或者使用任何支持运行带有嵌入式 jar 的 jar 的工具。看看这个或只是谷歌“罐子里的罐子”,你会得到大量的点击。

于 2012-10-01T06:43:57.543 回答