Java11: 通过 Shebang 执行源文件不工作

Java 11: Executing Source File via Shebang is not working

我想看看两天前发布的 java 11 的一些新功能。 JEP 330 声明我可以在不编译的情况下启动 Java-Source-Code-Program。 它还应该支持 Shebang-Files 的使用。

因此我写了这个小的 Hello-World 程序 Test.java:

#!/opt/java/jdk-11/bin/java --source 11

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

downloaded JDK 11提取到/opt/java。 因此,Shebang 本身正在发挥作用。 IE。执行 /opt/java/jdk-11/bin/java --version 给我

openjdk 11 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

使 Test.java 可执行(使用 chmod +x Test.java)后,执行失败。 IE。 ./Test.java 给我:

./Test.java:1: error: illegal character: '#'
#!/opt/java/jdk-11/bin/java --source 11
^
./Test.java:1: error: class, interface, or enum expected
#!/opt/java/jdk-11/bin/java --source 11
^
2 errors
error: compilation failed

一旦我从 Test.java 中删除 Shebang-Line 并从 /opt/java/jdk-11/bin/java --source 11 Test.java 开始 一切都很顺利,我得到了预期的输出:Hello World!

我的机器是运行Ubuntu 17.04。 我已将 javac 链接到 JDK 11 中的那个(即执行 javac -version 给出 javac 11)。

经过反复试验,我找到了正确的解决方案。 是文件扩展名 .java 导致了这些问题。

即如果我将文件重命名为 Test.sh 一切正常。

这是一个完整的 Hello-World-Shebang-Example:

创建一个文件Test.sh,内容类似于

#!/opt/java/jdk-11/bin/java --source 11

public class Test
{
    public static void main(String[] args)
    {
        System.out.println("Hello World!");
    }
}

使其可执行(即chmod +x Test.sh)。

最后但同样重要的是使用./Test.sh

执行它

根据您链接到的 JEP(参见 shebang files section),shebang 文件将用于启动 java 进程,而不是用作 java:

A shebang file to invoke the Java launcher using source-file mode must begin with something like:

#!/path/to/java --source version

For example, we could take the source code for a "Hello World" program, and put it in a file called hello, after an initial line of #!/path/to/java --source 10, and then mark the file as executable. Then, if the file is in the current directory, we could execute it with:

$ ./hello

换句话说,您要做的是使 Test.java 可执行。您还必须重命名它,因为当它被命名为 *.java.

时,它不会像 shebang 和删除第一行一样工作
$ move Test.java test
$ chmod +x test
$ ./test 

这将启动 shebang 处理器,它将去除第一行并将脚本的其余部分传递给 /path/to/java,Java 将编译脚本和 运行 主要方法。

文件名不得以 .java 结尾,以便 java 可执行文件忽略 shebang 行。您可以使用不同的扩展名,或者根本没有扩展名(这是他们在 JEP 示例中所做的,也是我推荐的)。

来自 JEP 330(已强调):

When the launcher reads the source file, if the file is not a Java source file (i.e. it is not a file whose name ends with .java) and if the first line begins with #!, then the contents of that line up to but not including the first newline are ignored when determining the source code to be passed to the compiler. The content of the file that appears after the first line must consist of a valid CompilationUnit as defined by §7.3 in the edition of the Java Language Specification that is appropriate to the version of the platform given in the --source option, if present, or the version of the platform being used to run the program if the --source option is not present.

不需要特别以“.sh”结尾;此外,这可能会产生误导,因为该文件实际上并不是 shell 脚本。