在 java shebang 脚本中加载库
Load library in a java shebang script
自 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(), "$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(), "$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
没有。
你的 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(), "$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(), "$saltsalt"));
}
}
$ ./kkkk.sh
$saltsalt$PXysoX71YwjJOoKzgzTEg/
注意:根据我的示例,编写此答案时 (JDK 11 ea) --class-path
参数需要位于 --source
之前。现在 (JDK 15) 参数的顺序无关紧要,任何一个顺序都可以。
这 在 OpenJDK <= 11.0.7
中通常不起作用 。这是否是一个错误并得到修复尚不清楚。有一个打开的错误报告:
https://bugs.openjdk.java.net/browse/JDK-8242911
指定 --class-path
至少适用于 OpenJDK 12.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
关于其他答案和评论中提到的其他事情的一些注释:
--source
必须是第一个参数。在 shebang 文件中,第一行被视为 #!$COMMAND $ONE-SINGLE-ARGUMENT
。所以 shell 不会用空格分隔 $ONE-SINGLE-ARGUMENT
。因此,如果 Java 启动器以 --source
开头并进一步处理其他参数,则 Java 启动器将按空格拆分参数。
- 我无法完全解释 muttonUp 的工作示例。我怀疑这与macOS的使用有关。也许使用过的 shell 已经分解了 shebang 参数。
- 因此,此问题可能仅限于某些 shell。我已经用 Ubuntu 的
bash
和 dash
. 测试了行为
如之前的回答所述,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
之前则无效
自 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(), "$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(), "$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
没有。
你的 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(), "$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(), "$saltsalt"));
}
}
$ ./kkkk.sh
$saltsalt$PXysoX71YwjJOoKzgzTEg/
注意:根据我的示例,编写此答案时 (JDK 11 ea) --class-path
参数需要位于 --source
之前。现在 (JDK 15) 参数的顺序无关紧要,任何一个顺序都可以。
这 在 OpenJDK <= 11.0.7
中通常不起作用 。这是否是一个错误并得到修复尚不清楚。有一个打开的错误报告:
https://bugs.openjdk.java.net/browse/JDK-8242911
指定 --class-path
至少适用于 OpenJDK 12.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
关于其他答案和评论中提到的其他事情的一些注释:
--source
必须是第一个参数。在 shebang 文件中,第一行被视为#!$COMMAND $ONE-SINGLE-ARGUMENT
。所以 shell 不会用空格分隔$ONE-SINGLE-ARGUMENT
。因此,如果 Java 启动器以--source
开头并进一步处理其他参数,则 Java 启动器将按空格拆分参数。- 我无法完全解释 muttonUp 的工作示例。我怀疑这与macOS的使用有关。也许使用过的 shell 已经分解了 shebang 参数。
- 因此,此问题可能仅限于某些 shell。我已经用 Ubuntu 的
bash
和dash
. 测试了行为
如之前的回答所述,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
之前则无效