【问题标题】:JRE not using classpath specified by manifest file of runnable jarJRE 未使用可运行 jar 的清单文件指定的类路径
【发布时间】:2018-01-03 19:24:01
【问题描述】:

第一次发帖,很抱歉我的格式不好。我有一个在 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

但是,当我尝试使用“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());
}

当我运行这段代码时,类路径就是“myJar.jar”。

我有两个问题:

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

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

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

【问题讨论】:

    标签: java manifest


    【解决方案1】:

    你在做什么听起来是正确的。

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

    我要检查的第一件事是myJar.jar 内的文件META-INF/MANIFEST.MF 是否与您创建的清单相匹配。您可以通过将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");
          }
      }
      
    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();
          }
      }
      
    7. 运行javac exe/myMain.java

    8. 在“experiment”目录下创建一个名为“manifest”的文件,内容如下:

        Main-Class: exe.myMain
        Class-Path: lib/jar_1.jar lib/jar_2.jar
        Manifest-Version: 1.0
    
    1. 运行jar cfm myJar.jar manifest exe/myMain.class

    2. 运行java -jar myJar.jar

    输出:

    /.../experiment/myJar.jar
    Hello from ClassInJar1
    

    【讨论】:

      【解决方案2】:

      您的manifest 文件似乎有误。你有Main-Class: exe.myMain => java 但有 exe 类型?为您推荐的是您应该使用 eclipse 导出您的 jar 文件,它会自动为您创建所有内容,您不必手动创建清单文件,因此您可能会出错。详见如下:

      我已经通过使用 eclipse 创建了一个 java 项目进行了测试 => 使用 eclipse 的导出功能导出可运行的 JAR => 使用第三个选项(将所需的库复制到子文件夹中......)。导出后,我得到了一个名为 myJarName.jar 的 jar 和一个名为 myJarName_lib 的文件夹。在META-INF 下用7zip 程序=> 打开jar => 打开MANIFEST.MF => 下面是它的结构:

      Manifest-Version: 1.0
      Class-Path: . myJarName_lib/gson-2.8.0.jar myJarName_lib/jsoup-1.8.3.jar myJarName_lib/commons-cli-1.2.jar myJarName_lib/jackson-core-2.8.8.jar
      Main-Class: upwork.Main
      

      【讨论】:

      • exe 部分是包名(文件扩展名位于文件名的末尾,Main-Class: 条目的值甚至不是文件名——它是一个合格的类名)。
      猜你喜欢
      • 1970-01-01
      • 2013-12-17
      • 2013-08-27
      • 1970-01-01
      • 2023-03-18
      • 2011-01-02
      • 1970-01-01
      相关资源
      最近更新 更多