【问题标题】:passing command line arguments to a specific **class** in a non-executable jar file将命令行参数传递给不可执行的 jar 文件中的特定 **class**
【发布时间】:2014-03-11 00:07:46
【问题描述】:

一些上下文: 我正在 Eclipse 中创建一个 Java 项目(仅使用 Eclipse 一周)。在中断了 13 年之后,我选择了 Java,因为我必须将文件从 IBM EBCDIC 5035 和 935 转换为 UTF-16。独立类(总共两个类)在 Eclipse 中运行良好。 每个类都有两个参数——源文件+位置和目标文件+位置 每个班级每晚将转换大约十几个文件。

所以现在我必须自动化解决方案并进行部署。我使用 Eclipse 创建了一个常规 jar(不是可运行的 jar),这样我就可以单独调用每个类,而无需创建“管理器”类。

在我运行以下命令时的命令提示符:

java -jar test.jar ConvFileCP_5035_To_UTF16 \\\\usanofp03\\Informatica\\Dev\\OutputFiles\\JDEJapanCustomer_CP939.txt \\\\usanofp03\\Informatica\\Dev\\OutputFiles\\JDEJapanCustomer。 txt

输出(通过 system.out... 确认)让我感到惊讶,因为 args[0] = ConvFileCP_5035_To_UTF16(类名!)和 args[1] = \\\\usanofp03\\Informatica\\Dev\\OutputFiles\\JDEJapanCustomer_CP939.txt

我转而使用 args[1] 和 args[2] 并且程序运行良好但我想知道为什么会发生这种情况以及在这里做什么是正确的

帮助将不胜感激! 谢谢,

【问题讨论】:

  • 我认为this 应该会给你答案。它描述了如何使用 -jar 选项,看起来你不应该给它另一个类名。 (我自己从未尝试过,所以我不能给你任何其他建议。)
  • 我不知道你所说的“可执行jar”;哪有这回事。您是指META-INF/MANIFEST.MF 中的Main-Class 条目吗?
  • 据我了解 - 当您创建一个可运行的 jar 时,您需要在 MANIFEST 中指定 MAIN(条目)类。在 Eclipse 中,有一个选项可以简单地创建一个 jar 文件(不可执行是我用词不当)。这是我用过的。我希望能够在 jar 中调用类,而不必使用我正在做的 Main-Class 条目。
  • 那么不要使用-jar,因为它需要Main-Class。将 jar 添加到您的类路径并调用 java name.of.MainClass <args here>

标签: java eclipse jar arguments


【解决方案1】:

注意:我知道这是一个老问题,但确实值得回答。

虽然提问者说他​​们“使用 Eclipse 创建了一个常规 jar(不是可运行的 jar)”,但看起来 Eclipse 可能实际上已经指定了其中一个类作为主类JAR,它解释了他们遇到的输出,即args[0] 持有他们打算运行的类的名称。

-jar 选项指示java“运行”给定的 JAR,这实际上导致java 在位于给定 JAR 内的清单中查找指定主类的行。运行 JAR 时,任何其他参数都将传递给清单指定的主类。

@fge 所说的之后,看起来提问者的经历可能是运行意外制作的可运行 JAR 的结果,该 JAR 应该被用作库,指定为-classpath 选项,当调用 java 并提供预期的类时。

如需进一步调查,请参阅以下示例。

使用下面的类,它枚举它接收的命令行参数,我们可以演示不同的java 调用的行为方式:

public class JarTest
{
  public static void main(String[] args)
  {
    for(int i = 0; i < args.length; i++)
    {
      System.out.println(i + ": " + args[i]);
    }
  }
}

像平常一样编译这个类(即javac JarTest.java),我们可以以通常的方式运行它并提供一些命令行参数来查看它的行为:

~/temp/jar-test$ java JarTest arg1 arg2
0: arg1
1: arg2

下面的命令会将这个类打包成一个基本的JAR:

~/temp/jar-test$ jar cf jar-test.jar JarTest.class

Java 教程的Running JAR-Packaged Software 章节的最后一部分,标题为“JAR 文件作为应用程序”,解释了直接“运行 JAR 打包应用程序”的唯一方法是使用 @ 987654336@ 选项如下:

~/temp/jar-test$ java -jar jar-test.jar
no main manifest attribute, in jar-test.jar

但是,正如我们在上面看到的,这并不容易。还要注意,即使明确指定预期的主类也无济于事:

~/temp/jar-test$ java -jar jar-test.jar JarTest arg1 arg2
no main manifest attribute, in jar-test.jar

正如我们将在下面看到的,这是因为指定 JAR 之后的任何内容都会成为主类的命令行参数,如果找到的话,那么java 命令本身就会有效地忽略它。当然,在上述情况下,这些参数实际上并没有传递给任何东西,因为 java 还不知道应该将它们传递给哪个类。

为了实际运行 JAR,java 命令需要知道哪个类是应用程序的入口点(即具有 main 方法的类),这在 JAR 的清单中通过 Main-Class 标头指定。如果不指定主类,我们会看到上述错误。 The Java Tutorials 的 Setting an Application's Entry Point 章节描述了如何在 JAR 的清单中指定主类。按照这些说明,我们创建manifest.txt,其内容如下(包括最后一个换行符):

Main-Class: JarTest

重新创建 JAR 并包含清单(有关 jar 命令的更多详细信息,请参阅 thisthis):

~/temp/jar-test$ jar cfm jar-test.jar manifest.txt JarTest.class

现在我们可以尝试运行我们的新 JAR:

~/temp/jar-test$ java -jar jar-test.jar JarTest arg1 arg2
0: JarTest
1: arg1
2: arg2

如我们所见,我们的 JAR 现在运行成功,输出类似于提问者好奇的输出。当运行通过包含的清单指定主类的 JAR 时,不需要指定预期的类,实际上,如果我们这样做,该字符串将作为 args[0] 传递给主类。

为了达到预期的结果,我们应该通过将 JAR 添加到类路径来运行我们的程序(最简单的方法是通过 -classpath-cp 选项)并指定要运行的类:

~/temp/jar-test$ java -cp jar-test.jar JarTest arg1 arg2
0: arg1
1: arg2

如果我们将此与前面的命令进行比较,唯一的区别是我们使用了-jar 选项,而现在我们使用了-cp 选项并实现了可能是提问者的意图。

这里可能值得注意的是,上面的 (-cp) 方法适用于基本 JAR(即没有清单指定的主类)或可运行 JAR,因为我们现在只是告诉 java在给定的 JAR 中查找指定的类。

【讨论】:

  • 这是一个很好的答案。您是否知道是否有一种方法可以避免在传递参数时指定 JarTest 并让它成为接受 args 的默认类?例如。 java -cp jar-test.jar arg1 arg2 但 arg1 和 arg2 默认传递给 JarTest。
猜你喜欢
  • 2010-11-26
  • 2013-11-21
  • 2011-12-28
  • 2016-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
  • 1970-01-01
  • 2014-06-19
相关资源
最近更新 更多