在没有构建工具的情况下编译可执行 jar 时依赖项的 NoClassDefFoundError

NoClassDefFoundError for dependencies when compiling executable jar with no build tools

我正在尝试将我的 Java 程序编译成一个可执行的 jar 文件,并且我尝试按照各个地方的所有说明进行操作,但是我遇到了一个问题。

Class 文件

我做的第一件事是使用此命令将所有内容编译成 class 文件。

javac -d ./build src/main/**/*.java -cp lib/main/commons-cli-1.4/commons-cli-1.4.jar:lib/main/commons-io-2.8.0/commons-io-2.8.0.jar

这会将 src/main 中的所有 .java 文件(我当然不想编译测试)编译到名为 build 的文件夹中。它还将 class 路径设置为代码所依赖的所有 .jar 文件(Apache Commons CLI 和 Apache Commons IO)。

Jar 文件

下一步是生成 .jar 文件。为此,我使用以下命令(在 cd ./build 之后)。

jar cvfm ../bin/program.jar manifest.txt .

此处,manifest.txt 位于文件夹 build 中,包含以下内容。 (根据文档指示,它以尾随换行符结尾。)

Main-Class: cli.Cli

这里的cli.Cli指的是位于src/main/cli/Cli.java中名为Cli的class,它包含了main方法。

运行 罐子

现在我使用以下命令尝试 运行 生成的 program.jar 文件,但出现此错误。

$ java -jar build/program.jar
Error: Unable to initialize main class cli.Cli
Caused by: java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException

此错误指的是 src/main/cli/Cli.java 中的一个导入语句,它应该与所有其他导入语句位于同一个 .jar 文件中。 IDE 确实识别导入,但我不确定为什么我无法 运行 文件。这是我从 Cli.java.

进口的摘录
package cli;

import java.io.IOException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.io.FilenameUtils;
// more imports...

编辑

我试图更改清单以包含 class 路径,但这似乎根本没有帮助。我尝试了以下两个版本的清单。

相对于bin/build/

Main-Class: cli.Cli
Class-Path: ../lib/main/commons-cli-1.4/commons-cli-1.4.jar:../lib/main/commons-io-2.8.0/commons-io-2.8.0.jar

相对于工作区文件夹(我运行jar时的当前目录):

Main-Class: cli.Cli
Class-Path: lib/main/commons-cli-1.4/commons-cli-1.4.jar:lib/main/commons-io-2.8.0/commons-io-2.8.0.jar

编辑 2

我将我的代码更改为不使用 ParseException 但是另一个导入导致了同样的错误。

原来清单中的类路径需要 space 分隔,每个 jar 的路径相对于 bin/,如下所示:

Main-Class: cli.Cli
Class-Path: ../lib/main/commons-cli-1.4/commons-cli-1.4.jar ../lib/main/commons-io-2.8.0/io-2.8.0.jar program.jar