在 java shebang 脚本中加载库

Ima*_*ica 6 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"));
  }
}
Run Code Online (Sandbox Code Playgroud)

可以运行

$ /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
Run Code Online (Sandbox Code Playgroud)

但以 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"));
  }
}
Run Code Online (Sandbox Code Playgroud)

我收到错误:

$ ./jscript.sh
Error: Could not find or load main class ..jscript.sh
Caused by: java.lang.ClassNotFoundException: //jscript/sh
Run Code Online (Sandbox Code Playgroud)

问题出--class-path在第一行的参数上。由于某种原因,--souce争论得以通过,但又--class-path没有通过。

小智 5

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

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

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

#!/usr/bin/env -S java --class-path /path/mylib.jar --source 11
Run Code Online (Sandbox Code Playgroud)

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


Sco*_*tus 4

这通常在 OpenJDK <= 中不起作用11.0.7。目前还不清楚这是否是一个错误并得到修复。有一个开放的错误报告:

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

指定--class-path至少与 OpenJDK12.0.2和14.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
Run Code Online (Sandbox Code Playgroud)

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

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

  • 你可以通过将其委托给 env 来绕过这个愚蠢的 shebang 解析:`#!/bin/env -S java --source 11 --more-arguments` (2认同)