我想知道如何创建一个包含多个包的 jar 文件

问题描述

我已经阅读了大约 100 页关于将 java 项目打包成 jar 文件内容,花了两天时间尝试了所有不同类型的类路径组合,但未能找到解决此问题的方法

我有两个包,每个包都有一个文件

package frontend.timer;

import backend.Activity;

public class Main {

    public static void main(String[] args) {
        System.out.println("Hello world");
        Activity myAct = new Activity();
        System.out.println(myAct.greeting());
    }
}

和....

package backend;

public class Activity {

    public String greeting() {

        return "Goodby";

    }
}

当我编译并运行项目时:

dir /s /B *.java >sources.txt
javac -d outDir @sources.txt
java -classpath outDir  frontend.timer.Main

它运行良好。

然后我创建了一个清单文件

Main-Class: frontend.timer.Main
Class-Path: outDir/
<blanc line here>

并压缩并使用 jar 文件运行它:

jar.exe cfm timer.jar manifest.mf outDir\frontend\timer outDir\backend
java -jar timer.jar

它再次运行良好。

为了澄清jar文件内容是:

meta-inf/
meta-inf/MANIFEST.MF
outDir/frontend/timer/
outDir/frontend/timer/Main.class
outDir/backend/
outDir/backend/Activity.class

现在,当我将 jar 复制到另一个文件夹时,它不会运行:

mkdir newDir 
copy timer.jar newDir 
java -jar newDir\timer.jar
Error: Could not find or load main class frontend.timer.Main
Caused by: java.lang.classNotFoundException: frontend.timer.Main

只需将 outDir 的内容复制到 newDir 即可解决。但这对我来说没有意义。 创建两个 jar 文件一个用于前端,一个用于后端)会产生完全相同的结果。一切正常,直到我将其移动到另一个目录。

我错过了什么,看不到,找不到?

解决方法

您已经使用内置的 Class-Path: outDir/ 构建了 MANIFEST.MF,这意味着在运行时会扫描该目录以查找您的打包类。这就是为什么将 outDir 复制到 newDir 解决了一个问题,java 是从 outDir 文件夹而不是 jar 加载类。

通过从 MANIFEST.MF 中删除 Class-Path: outDir/ 条目来解决此问题

下一个问题是您使用额外的目录路径前缀 outDir/ 打包了您的类。 jar 的正确布局应该是:

META-INF/
META-INF/MANIFEST.MF
frontend/timer/
frontend/timer/Main.class
backend/
backend/Activity.class

在包含 outDir 和前端/后端文件夹的 META-INF/MANIFEST.MF 中构建 jar 的分解结构,然后一步创建 jar:

cd outDir
jar cvf ..\timer.jar .

这意味着 jar 具有相同的结构 outDir 以及您使用分解文件夹进行测试的方式。希望这些将是等效的:

java -classpath outDir    frontend.timer.Main
java -classpath timer.jar frontend.timer.Main

我建议您在 jar 测试之前也重命名 outDir => outDir.temp 以验证第二个调用是否使用 JAR 而不是 outDir 的内容运行。