Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load library in a java shebang script

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.

like image 364
Imaskar Avatar asked Mar 06 '23 13:03

Imaskar


2 Answers

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.
like image 151
Scolytus Avatar answered Mar 16 '23 08:03

Scolytus


As told in previous answers there is a bug in java 11:

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

I found this work around that let me use the class-path parameter:

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

Note the order of the parameters, if --source is before --class-path it does not work.

like image 34
Masar Avatar answered Mar 16 '23 08:03

Masar