【问题标题】:Executable Jar with depedencies具有依赖关系的可执行 Jar
【发布时间】:2011-04-14 19:27:47
【问题描述】:

我正在尝试从命令行构建一个可执行 jar(我不想使用 ant 或 OneJar )。这是我的 file.jar 的内容:

jar tvf file.jar
     0 Mon Sep 20 17:16:12 CEST 2010 lib/
 45396 Mon Sep 20 17:16:12 CEST 2010 lib/org.apache.commons.logging_1.0.4.v201005080501.jar
321330 Mon Sep 20 17:16:12 CEST 2010 lib/org.apache.commons.httpclient_3.1.0.v201005080502.jar
 55003 Mon Sep 20 17:16:12 CEST 2010 lib/org.apache.commons.codec_1.3.0.v20100518-1140.jar
     0 Mon Sep 20 19:15:00 CEST 2010 META-INF/
   265 Mon Sep 20 19:12:44 CEST 2010 META-INF/MANIFEST.MF
530609 Mon Sep 20 17:16:12 CEST 2010 ped.jar

META-INF/MANIFEST.MF 的内容:

Manifest-Version: 1.0
Class-Path: ped.jar lib/org.apache.commons.codec_1.3.0.v20100518-1140.jar lib/org.apache.commons.httpclient_3.1.0.v201005080502.jar lib/org.apache.commons.logging_1.0.4.v201005080501.jar
Main-Class: fr.inserm.umr915.bomcat.ped.PedigreeDrawer

而且 ped.jar 确实包含主类

jar tvf ped.jar | grep PedigreeDrawer.class
 39541 Mon Sep 20 17:16:10 CEST 2010 fr/inserm/umr915/bomcat/ped/PedigreeDrawer.class

但是当我尝试执行 file.jar 时,出现错误:

java -jar file.jar
Exception in thread "main" java.lang.NoClassDefFoundError: fr/inserm/umr915/bomcat/ped/PedigreeDrawer
Caused by: java.lang.ClassNotFoundException: fr.inserm.umr915.bomcat.ped.PedigreeDrawer
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

所以,我在这里遗漏了一些东西。我不能只包含依赖项来打包一个可执行的 jar 吗?

感谢您的帮助

皮埃尔

【问题讨论】:

    标签: java jar packaging executable-jar


    【解决方案1】:

    文件manifest.mf 中的值“Class-Path”指定您的类路径,就好像您将在没有-jar 但使用-classpath lib/... 参数的情况下启动应用程序一样。路径是在本地解释的,而不是在您的 jar 文件中。

    另一种方法是使用one-jar 或使用特殊的类加载器来查看包含在外部 jar 文件中的 jar 文件。

    使用JCL,您可以直接从嵌入式 jar 加载您的类,如下所示:

      JarClassLoader jcl=new JarClassLoader();
      jcl.add("myjar.jar"); // Add some class source
    
      jcl.getSystemLoader().setOrder(1); // Look in system class loader first
      jcl.getLocalLoader().setOrder(2); // if not found look in local class loader
      jcl.getParentLoader().setOrder(3); // if not found look in parent class loader
      jcl.getThreadLoader().setOrder(4); // if not found look in thread context class loader
      jcl.getCurrentLoader().setOrder(5); // if not found look in current class loader
    
      // A custom class loader that extends org.xeustechnologies.jcl.ProxyClassLoader
      MyLoader loader=new MyLoader();
      loader.setOrder(6);
    
      jcl.addLoader(loader); //Add custom loader
    

    但是你必须将 jcl 添加到你的类路径中......或者将分解的 jcl 添加到你的 jar 中。

    【讨论】:

    • 所以这意味着整个归档文件.jar 必须被提取不是吗?
    【解决方案2】:

    OneJar 旨在解决此类问题。你可以编写一个自定义的类加载器来达到同样的效果。

    【讨论】:

      【解决方案3】:

      如前所述,Class-Path: 属性中的 jar 与 jar 文件的位置相关,而不是在 jar 文件中。这可能是 Java 用于运行小程序时的遗留物。

      您需要使用 maven uberjar 之类的工具将所有需要的类拼凑到一个 jar 中,以创建一个独立的可执行 jar。

      如果您绝对不想使用工具,当然也可以将所有 jar 解压缩到一个目录中,添加 META-INF 和清单,然后再次压缩所有内容。

      【讨论】:

        【解决方案4】:

        如果没有特殊包装(例如 OneJar 等),您不能在 Jar 中包含 Jar。

        如果您真的不想使用 OneJar(或其他类似工具),则需要在您的可分发文件中包含多个 Jar 文件。

        【讨论】:

          【解决方案5】:

          什么是file.jar
          您可以尝试像这样设置类路径:

          Class-Path: lib/org.apache.commons.codec_1.3.0.v20100518-1140.jar lib/org.apache.commons.httpclient_3.1.0.v201005080502.jar lib/org.apache.commons.logging_1.0.4.v201005080501.jar
          

          然后像这样运行你的 jar 文件:

          java -jar ped.jar
          

          【讨论】:

          • files.jar 是存档。它包含 ped.jar 和 lib/*.jar ,所以我不能运行“java -jar ped.jar”,除非我从存档中提取它,(我不想这样做)。
          猜你喜欢
          • 2018-10-03
          • 2010-10-09
          • 1970-01-01
          • 2021-05-25
          • 2016-02-09
          • 2018-09-03
          相关资源
          最近更新 更多