在没有构建工具的情况下编译可执行 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
我正在尝试将我的 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