来自罐子内部的 NoClassDefFoundError
NoClassDefFoundError from inside a jar
上下文
为了学习使用 ant,我做了一个小型的概念验证项目:
我创建了一个小 JAR 文件,其中只包含一个 class,您可以在此处看到:
public class Dummy {
private String name;
public Dummy(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
我制作了一个名为 lib/dummy.jar
的 JAR。这是它的清单:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.10.5
Created-By: 1.8.0_232-b09 (Oracle Corporation)
Class-Path:
项目
现在,我想在如下所示的主 class 中使用该 JAR:
public class Main {
public static void main(String[] args) {
Dummy f = new Dummy("Hello, World!");
System.out.println(f.getName());
}
}
我可以毫无问题地编译它(如果我在 class 路径中包含我的 JAR)。
然后,我尝试制作一个主要的 JAR class。 JAR 包含以下内容:
META-INF/
|- MANIFEST.MF
Main.class
dummy.jar
清单包含:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.10.5
Created-By: 1.8.0_232-b09 (Oracle Corporation)
Main-Class: Main
Class-Path: dummy.jar
JAR 创建成功。
问题
如果我尝试 运行 JAR,我有一个 Exception in thread "main" java.lang.NoClassDefFoundError: Dummy
代码应该可以工作,因为如果我在 运行ning 时在 class 路径中包含我的初始 dummy.jar
,一切正常。 (java -cp build/jar/run-me.jar:lib/dummy.jar Main
)
为什么当我 运行 JAR 单独运行时它不起作用?
build.xml
如果有用的话,这是我的build.xml
(在评论中欣然接受的改进):
<project default="all">
<path id="build.classpath">
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</path>
<pathconvert property="mf.classpath" pathsep=" ">
<path refid="build.classpath" />
<flattenmapper />
</pathconvert>
<target name="all" depends="compile,jar,run" />
<target name="compile">
<mkdir dir="build/classes" />
<javac srcdir="src" destdir="build/classes" includeantruntime="false">
<classpath>
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</classpath>
</javac>
</target>
<target name="jar">
<mkdir dir="build/jar" />
<jar destfile="build/jar/run-me.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="Main" />
<attribute name="Class-Path" value="${mf.classpath}" />
</manifest>
<path id="build.classpath">
<fileset dir="lib">
<include name="**/*.jar" />
<include name="**/*.zip" />
</fileset>
</path>
</jar>
</target>
<target name="run">
<java jar="build/jar/run-me.jar" fork="true"></java>
</target>
<target name="clean">
<delete dir="build" />
</target>
</project>
Class-Path: dummy.jar
表示它在 与 run-me.jar
相同的文件夹 中查找 dummy.jar
。它不会在里面run-me.jar
.
寻找它
由于 run-me.jar
在 build/jar
中,而 dummy.jar
在 lib
中,您需要指定 Class-Path: ../../lib/dummy.jar
才能正常工作。
最好保留 Class-Path: dummy.jar
并在 运行 时将两个 jar 文件放在同一个文件夹中。
上下文
为了学习使用 ant,我做了一个小型的概念验证项目:
我创建了一个小 JAR 文件,其中只包含一个 class,您可以在此处看到:
public class Dummy {
private String name;
public Dummy(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
我制作了一个名为 lib/dummy.jar
的 JAR。这是它的清单:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.10.5
Created-By: 1.8.0_232-b09 (Oracle Corporation)
Class-Path:
项目
现在,我想在如下所示的主 class 中使用该 JAR:
public class Main {
public static void main(String[] args) {
Dummy f = new Dummy("Hello, World!");
System.out.println(f.getName());
}
}
我可以毫无问题地编译它(如果我在 class 路径中包含我的 JAR)。
然后,我尝试制作一个主要的 JAR class。 JAR 包含以下内容:
META-INF/
|- MANIFEST.MF
Main.class
dummy.jar
清单包含:
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.10.5
Created-By: 1.8.0_232-b09 (Oracle Corporation)
Main-Class: Main
Class-Path: dummy.jar
JAR 创建成功。
问题
如果我尝试 运行 JAR,我有一个 Exception in thread "main" java.lang.NoClassDefFoundError: Dummy
代码应该可以工作,因为如果我在 运行ning 时在 class 路径中包含我的初始 dummy.jar
,一切正常。 (java -cp build/jar/run-me.jar:lib/dummy.jar Main
)
为什么当我 运行 JAR 单独运行时它不起作用?
build.xml
如果有用的话,这是我的build.xml
(在评论中欣然接受的改进):
<project default="all">
<path id="build.classpath">
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</path>
<pathconvert property="mf.classpath" pathsep=" ">
<path refid="build.classpath" />
<flattenmapper />
</pathconvert>
<target name="all" depends="compile,jar,run" />
<target name="compile">
<mkdir dir="build/classes" />
<javac srcdir="src" destdir="build/classes" includeantruntime="false">
<classpath>
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</classpath>
</javac>
</target>
<target name="jar">
<mkdir dir="build/jar" />
<jar destfile="build/jar/run-me.jar" basedir="build/classes">
<manifest>
<attribute name="Main-Class" value="Main" />
<attribute name="Class-Path" value="${mf.classpath}" />
</manifest>
<path id="build.classpath">
<fileset dir="lib">
<include name="**/*.jar" />
<include name="**/*.zip" />
</fileset>
</path>
</jar>
</target>
<target name="run">
<java jar="build/jar/run-me.jar" fork="true"></java>
</target>
<target name="clean">
<delete dir="build" />
</target>
</project>
Class-Path: dummy.jar
表示它在 与 run-me.jar
相同的文件夹 中查找 dummy.jar
。它不会在里面run-me.jar
.
由于 run-me.jar
在 build/jar
中,而 dummy.jar
在 lib
中,您需要指定 Class-Path: ../../lib/dummy.jar
才能正常工作。
最好保留 Class-Path: dummy.jar
并在 运行 时将两个 jar 文件放在同一个文件夹中。