Load library in a java shebang script

二次信任 提交于 2020-04-29 10:08:26

问题


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 and dash.



回答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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!