【问题标题】:Java 11: Executing Source File via Shebang is not workingJava 11:通过 Shebang 执行源文件不起作用
【发布时间】:2019-03-02 23:36:45
【问题描述】:

我想看看两天前发布的 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)。

【问题讨论】:

  • 这只是 1) OpenJDK 2) Unix 风格操作系统的唯一选项...即。它适用于 Windows 吗?

标签: java shebang java-11


【解决方案1】:

根据你链接的JEP(见shebang files section),shebang文件是用来启动java进程的,不是java的参数:

使用源文件模式调用 Java 启动器的 shebang 文件必须以以下内容开头:

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

例如,我们可以获取“Hello World”程序的源代码,并将其放在名为 hello 的文件中,在 #!/path/to/java --source 10 的初始行之后,然后将该文件标记为可执行文件。然后,如果文件在当前目录中,我们可以执行它:

$ ./hello

换句话说,您想要做的是让Test.java 可执行。您还必须重命名它,因为当它被命名为 *.java 时,它不能作为 shebang 和剥离第一行。

$ move Test.java test
$ chmod +x test
$ ./test 

这将启动 shebang 处理器,该处理器将剥离第一行并将脚本的其余部分传递给 /path/to/java,Java 将编译脚本并运行 main 方法。

【讨论】:

  • 这个不行,脚本文件名不应该有.java后缀
  • @andrej 你注意到它在这个答案中被重命名了吗?
  • @ernest-k 不。我的错。对不起。也许你可以提到这个重要的重命名
  • @ernest_k move 是一个 Windows 命令。 UNIX 等价物是 mv
【解决方案2】:

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

来自JEP 330(已添加重点):

启动器读取源文件时,如果该文件不是Java源文件(即不是名称以.java结尾的文件)并且如果第一行以#! ,则在确定要传递给编译器的源代码时,忽略该行的内容,但不包括第一个换行符。出现在第一行之后的文件内容必须由 Java 语言规范版本中第 7.3 节定义的有效 CompilationUnit 组成,该版本适用于 --source 选项中给出的平台版本(如果存在),或用于运行程序的平台版本(如果 --source 选项不存在)。

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

【讨论】:

  • 我认为这很愚蠢。为什么它甚至应该关注文件名来改变它的行为?据我所知,即使文件名以 .java 结尾,忽略 shebang 也没有任何缺点。
【解决方案3】:

一些试验和错误给了我正确的解决方案。 是文件扩展名.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执行它

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多