使用Java shebang脚本加载库

时间:2018-08-23 14:49:04

标签: java shell java-11

自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没有通过。

3 个答案:

答案 0 :(得分: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

其他答案和评论中提及的其他事项的一些注释:

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

答案 1 :(得分: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/

答案 2 :(得分:1)

如先前的回答所述,java 11中存在一个错误:

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

我发现这种解决方法使我可以使用class-path参数:

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

请注意参数的顺序,如果--source--class-path之前不起作用。