【问题标题】:Load library in a java shebang script在 java shebang 脚本中加载库
【发布时间】:2018-08-23 14:49:04
【问题描述】:

从 JDK-11 开始,我们可以直接运行 java 源代码。这段代码

import org.apache.commons.codec.digest.Md5Crypt;

public class Oneliner {
  public static void main(String[] args){
    System.out.println(Md5Crypt.md5Crypt("ok".getBytes(), "$1$saltsalt"));
  }
}

可以用

运行
$ /usr/lib/jvm/jdk-11/bin/java --source 8 -cp /home/imaskar/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.jar jscript.java

但是以 shell 脚本形式(shebang)

#!/usr/lib/jvm/jdk-11/bin/java --source 8 --class-path /home/imaskar/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.jar

import org.apache.commons.codec.digest.Md5Crypt;

public class Oneliner {
  public static void main(String[] args){
    System.out.println(Md5Crypt.md5Crypt("ok".getBytes(), "$1$saltsalt"));
  }
}

我收到一个错误:

$ ./jscript.sh
Error: Could not find or load main class ..jscript.sh
Caused by: java.lang.ClassNotFoundException: //jscript/sh

问题在于第一行的--class-path 参数。出于某种原因,--souce 参数通过,但 --class-path 没有。

【问题讨论】:

  • 给定参数jscript.sh,java尝试执行jscript包中的sh类,所以我认为你需要将文件重命名回jscript.java(这不应该防止shebang解释)。而且,我在你的--class-path参数中没有看到包含你的java文件的目录,这一定是个问题。
  • @Aaron 在 jdk-11 他们为此提供了便利。使用--source 选项java 知道这是一个源文件名。
  • 感谢您提供的信息,我应该阅读 JEP。在你的错误中看起来它仍然试图加载一个 sh 类,但我想这是因为参数没有像你说的那样正确解析。

标签: java shell java-11


【解决方案1】:

你的shebang论点是错误的。

--class-path 必须在--source 之前

提到了in the original JEP,但它相当深奥,分为几个部分......

以下将起作用。

#!/usr/lib/jvm/jdk-11/bin/java --class-path /home/imaskar/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.jar --source 8 

import org.apache.commons.codec.digest.Md5Crypt;

public class Oneliner {
  public static void main(String[] args){
    System.out.println(Md5Crypt.md5Crypt("ok".getBytes(), "$1$saltsalt"));
  }
}

我的版本在下面

$ /usr/bin/java -version
java version "11" 2018-09-25
Java(TM) SE Runtime Environment 18.9 (build 11+28)
Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11+28, mixed mode)

$ cat kkkk.sh
#!/usr/bin/java --class-path /Users/steven/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.jar --source 8

import org.apache.commons.codec.digest.Md5Crypt;

public class Oneliner {
    public static void main(String[] args){
        System.out.println(Md5Crypt.md5Crypt("ok".getBytes(), "$1$saltsalt"));
    }
}

$ ./kkkk.sh
$1$saltsalt$PXysoX71YwjJOoKzgzTEg/

注意:根据我的示例,编写此答案时(JDK 11 ea)--class-path 参数需要位于 --source 之前。现在(JDK 15)参数的顺序无关紧要,任何一个顺序都可以。

【讨论】:

  • Unrecognized option: --class-path /home/imaskar/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.ja Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.
  • @Imaskar 确保您没有任何带有 cat -A 的奇怪字符?
  • @Aaron 不,没什么异常。顺便说一句,感谢您提供有趣的命令。
  • 什么操作系统?我在 Ubuntu 16.04 和 17.10 上进行了测试。我发现它可以通过 args-file 工作。单个脚本仍然没有成功。
  • 这个答案是错误的,--source必须是第一个。
【解决方案2】:

通常在 OpenJDK 11.0.7 中不起作用。这是否是一个错误并得到修复尚不清楚。有一个打开的错误报告:

https://bugs.openjdk.java.net/browse/JDK-8242911

指定 --class-path 至少适用于 OpenJDK 12.0.214.0.1。 所以我假设对 Java 12 所做的一些改进解决了这个问题。

所以问题中的那一行应该可以工作,不需要改变:

#!/usr/lib/jvm/jdk-11/bin/java --source 8 --class-path /home/imaskar/.m2/repository/commons-codec/commons-codec/1.11/commons-codec-1.11.jar

关于其他答案和 cmets 中提到的其他事项的一些说明:

  • --source 必须是第一个参数。在 shebang 文件中,第一行被视为#!$COMMAND $ONE-SINGLE-ARGUMENT。所以shell不会用空格分隔$ONE-SINGLE-ARGUMENT。因此,如果参数以 --source 开头,Java 启动器将按空格分割参数,并进一步处理其他参数。
  • 我无法完全解释 muttonUp 的工作示例。我怀疑这与 macOS 的使用有关。也许使用过的 shell 已经拆分了 shebang 参数。
  • 因此,此问题可能仅限于某些 shell。我已经用 Ubuntu 的 bashdash 测试了这个行为。

【讨论】:

  • 确实,在 MacOS 中 --source 现在对我来说是第一和第二(使用 java 14),根据规范不应该是这种情况。
  • 你可以通过将它委托给 env 来绕过那个愚蠢的 shebang 解析:#!/bin/env -S java --source 11 --more-arguments
【解决方案3】:

正如之前的答案所述,java 11 中存在一个错误:

https://bugs.openjdk.java.net/browse/JDK-8242911

我发现这项工作让我可以使用类路径参数:

#!/usr/bin/env -S java --class-path /path/mylib.jar --source 11

注意参数的顺序,如果--source--class-path之前就不行了。

【讨论】:

    猜你喜欢
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-24
    • 2011-03-08
    • 2014-04-21
    • 1970-01-01
    相关资源
    最近更新 更多