问题
Since JDK-11 we have ability to run java source code directly. This code
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"));
}
}
can be run with
$ /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
But in a shell script form (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"));
}
}
I get an error:
$ ./jscript.sh
Error: Could not find or load main class ..jscript.sh
Caused by: java.lang.ClassNotFoundException: //jscript/sh
The problem is --class-path
argument in the first line. For some reason --souce
argument gets through, but --class-path
doesn't.
回答1:
This does not generally work in OpenJDK <= 11.0.7
. Whether this is a bug and gets fixed or not is not clear yet. There is an open bug report:
https://bugs.openjdk.java.net/browse/JDK-8242911
Specifying the --class-path
works at least with OpenJDK 12.0.2
and 14.0.1
.
So I assume some improvements made for Java 12 fixed this issue.
So the line in the question is supposed to work, no change needed:
#!/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
Some notes on other things mentioned in the other answer and in the comments:
--source
must be the first argument. In shebang files, the first line is treated like#!$COMMAND $ONE-SINGLE-ARGUMENT
. So the shell will not separate the$ONE-SINGLE-ARGUMENT
by whitespace. Thus, the Java launcher will split the argument by whitespace iff it starts with--source
and further process the other arguments.- I can't fully explain muttonUp's working example. I suspect it is related to the usage of macOS. Maybe the used shell split up the shebang argument already.
- Thus, it might be that this issue is limited to certain shells. I have tested the behavior with Ubuntu's
bash
anddash
.
回答2:
Your shebang arguments are the wrong way round.
--class-path
needs to come before --source
It is mentioned in the original JEP, but it rather esoteric, and split across a couple of sections...
The below will work.
#!/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"));
}
}
My Version is below
$ /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/
来源:https://stackoverflow.com/questions/51988546/load-library-in-a-java-shebang-script