JEP proposed to target JDK 11: 330: Launch Single-File Source-Code Programs

Stuart Marks stuart.marks at
Thu May 24 05:08:03 UTC 2018

On 5/22/18 7:43 AM, Peter Levart wrote:
> If this JEP added a feature that specifying source file name as "-" would read 
> STDIN as the Java source file, one could write executable scripts in the 
> following "hybrid" way:
> #!/bin/bash
> exec /path/to/java - $* <<EOF
> public class Hello {
>      public static void main(String[] args) {
>          System.out.println("Hello world");
>      }
> }
> Notice that this does not need shebang support from java launcher. The benefit 
> of this approach would also be that /path/to/java could be computed by the bash 
> script prefixing the Java source. Java typically does not have a standard 
> installation "place" like bash, so shebang scripts with hard-coded java path 
> would be less portable as bash scripts.

> Support for "-" STDIN source in java launcher does have one drawback. Scripts
> written this way can not process STDIN passed to the script as STDIN of java
> launcher is redirected to obtain Java source.

Hi Peter,

This is an excellent point: one can use a shell script "wrapper" to do all kinds 
of interesting things in addition to computing the path to java, such as 
supplying additional arguments based on other logic, etc.

I'll note that while "-" as a filename is a fairly strong convention, it isn't 
strictly necessary; /dev/stdin can be used on many systems as a filename that 
represents stdin. As you note this prevents the script's stdin from being read 
by the Java program. Instead, one can use a here-document with a file descriptor 
and then use /dev/fd/n as the "source file" to be compiled and run.

This is system-specific, of course, but these facilities should be widely 
available. I tested this on a Mac using Jon's patch from a couple weeks ago, [1] 
and it works fine. I'm sure Linux has the /dev/fd stuff as well. Also, the 
--source option must be used to coax the launcher to compile a file that doesn't 
end in ".java".

This is a little clunky, but it's no worse than the bits of magic you'd have to 
put at the top of a perl script in order to run it as a shell script.

Here's an example:



exec java --source 11 /dev/fd/3 "$@" 3<<EOF 

public class Hello { 

     public static void main(String[] args) { 

         String name = System.console().readLine("Please enter your name: "); 

         System.console().printf("Hello, %s!%n", name); 





$ ./
Please enter your name: Stuart
Hello, Stuart!




More information about the jdk-dev mailing list