JRE 不使用可运行 jar 的清单文件指定的类路径

fji*_*nez 5 java manifest

第一次发帖,对于我的格式不佳深表歉意。我有一个在eclipse中开发的java程序。我将程序导出为 jar (myJar.jar),然后将程序所依赖的所有外部 jar 放入名为lib的文件夹中,该文件夹与 myJar.jar 位于同一位置。为了设置我的类路径,我有一个具有以下格式的清单文件:

Main-Class: exe.myMain
Class-Path: lib/jar_1.jar lib/jar_2.jar ... lib/jar_n.jar
Manifest-Version: 1.0
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试使用“java -jar myJar.jar”运行程序时, lib中的 jar 中的类不会被加载(我收到 ClassNotFoundException)。我在程序中使用以下代码来打印类路径:

ClassLoader cl = ClassLoader.getSystemClassLoader();
URL[] urls = ((URLClassLoader)cl).getURLs();
for(URL url:urls){
    System.out.println(url.getFile());
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时,类路径只是“myJar.jar”。

我有两个问题:

1.) 上面的代码实际上在运行时为我提供了 JRE 的类路径,还是只是为我提供了主类的地址?

2.) 鉴于上面的代码确实在运行时为我提供了 JRE 的类路径,我做错了什么吗?

请随时询问更多信息,我很乐意提供您所需的信息。

tom*_*tom 2

你正在做的事情听起来是正确的。

由于某种原因,Class-Path在检查类路径时清单中的条目不会显示(例如,此处此处;这些示例使用该属性"java.class.path",但我的测试显示其ClassLoader.getURLs()行为相同)。不过,仍然应该搜索它的类。我不知道如何获取包含Class-Path清单中条目的真实类路径。

META-INF/MANIFEST.MF我要检查的第一件事是里面的文件是否myJar.jar与您创建的清单相匹配。您可以myJar.jar通过将其重命名为具有.zip文件扩展名来打开。

我尝试复制您的问题,但其中的类lib/jar_1.jar已为我加载,因此如果META-INF/MANIFEST.MF正确,我将详细描述我所做的事情,以便您可以找到我们正在做的不同事情。

编辑:

以下是我使用的步骤:

  1. 创建一个名为“experiment”的新目录。下面的步骤都是在该目录下完成的。

  2. 创建名为“jar_1”、“lib”和“exe”的新目录

  3. 在目录“jar_1”中创建一个名为“ClassInJar1.java”的文件,其中包含以下内容:

    package jar_1;
    
    public class ClassInJar1 {
        public static void method() {
            System.out.println("Hello from ClassInJar1");
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 跑步javac jar_1/ClassInJar1.java

  5. 跑步jar cf lib/jar_1.jar jar_1/ClassInJar1.class

  6. 在目录“exe”中创建一个名为“myMain.java”的文件,其中包含以下内容:

    package exe;
    
    import java.net.*;
    import jar_1.ClassInJar1;
    
    public class myMain {
        public static void main(String[] args) {
            ClassLoader cl = ClassLoader.getSystemClassLoader();
            URL[] urls = ((URLClassLoader) cl).getURLs();
            for (URL url : urls) {
                System.out.println(url.getFile());
            }
            ClassInJar1.method();
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  7. 跑步javac exe/myMain.java

  8. 在“experiment”目录中创建一个名为“manifest”的文件,其中包含以下内容:

package jar_1;

public class ClassInJar1 {
    public static void method() {
        System.out.println("Hello from ClassInJar1");
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 跑步jar cfm myJar.jar manifest exe/myMain.class

  2. 跑步java -jar myJar.jar

输出:

package exe;

import java.net.*;
import jar_1.ClassInJar1;

public class myMain {
    public static void main(String[] args) {
        ClassLoader cl = ClassLoader.getSystemClassLoader();
        URL[] urls = ((URLClassLoader) cl).getURLs();
        for (URL url : urls) {
            System.out.println(url.getFile());
        }
        ClassInJar1.method();
    }
}
Run Code Online (Sandbox Code Playgroud)