Draft JEP: Launch Single-File Source-Code Programs

John Rose john.r.rose at oracle.com
Mon Feb 12 18:42:49 UTC 2018


On Feb 12, 2018, at 8:47 AM, Brian Goetz <Brian.Goetz at Oracle.COM> wrote:

> The alternative — intruding this convention on the Java language syntax — is certainly a worse tradeoff. Think of this as “launcher 90% full” rather than “language 10% empty” :)


This is all good, and I agree that we don't need to add shebang to
the JLS. (See argument below.)  But, the proposal doesn't fully
match the design of shebang processing.  I'd like to discuss that
and propose a slight tweak.

The purpose of the shebang is to allow a Unix command to be
implemented by a script file with a designated script interpreter.
This only works if the file is executable and is implemented by
the system call execve[1].  BTW, marking a file executable without a
shebang sends it to /bin/sh, but by a higher layer[2] of the system,
not used in all cases.

[1] https://linux.die.net/man/2/execve <https://linux.die.net/man/2/execve>  (OS-level definition of shebang)
[2] https://linux.die.net/man/3/execl <https://linux.die.net/man/3/execl>   (library function adds implicit #! /bin/sh)

This predates modern mechanisms, such as desktop launchers,
which systematically recognize file extensions and map them to
content types.  This is important:  Shebang doesn't care about
file name extensions.

The optional argument to the script interpreter, as supported by
shebang, allows the interpreter to be run in a non-default scripting
mode which accepts the two oddities which come from shebang:
1. the file starts with a shebang (which otherwise might be unexpected
by the interpreter), 2. the file name might not have an extension
expected by the interpreter (because it is a nondescript command
name, implemented by a script).  The dtrace '-s' option does this,
and so (I presume) would the java '--source' option.

Higher-level launchers, above the level of the "exec*" families,
look at file extensions, such as "*.jar" or "*.app".  These do
not integrate as directly with Unix shell scripting, since "exec*"
won't launch them.

The net:  The design of shebang expects the interpreter to (sometimes)
require nonstandard invocation modes to process the shebang file.
The physical form of the file name is insignificant to shebang processing,
although it may (of course) be significant to the interpreter.

A quick survey of shebangs on my Mac show the following interpreters
used on my $PATH: /bin/*sh [-vepf], *python [-OR], /usr/bin/env *,
perl* [-w], ruby, *lua, dtrace -[q]s.  Only dtrace uses a specific script flag
in all cases.

At least one language (lua) documents shebang stripping as lexical
exception, but only in a particular invocation mode.  We can get the
same effect by factoring the exception into the launcher, not the JLS.

The applications to the present case:  From the point of view of the
design and use of shebang, it is reasonable to treat shebang
as an extra-linguistic construct, to be stripped by a special mode
of the script language processor (java).  From the same point of view,
it is not reasonable to require a special file extension (such as *.java)
to the shebang file, since that removes the main use case of shebang,
building arbitrary Unix commands on top of scripts.

So, if we want to properly integrate with the shebang, we need to drop
the requirement that the file name end with ".java", in the presence
of the "--source" option.  If the "--source" option is missing, it's fine
to require the "*.java" file name extension, as a nod to EOU.

And it's fine to have non-standard file processing (shebang removal)
under a special invocation mode ("java --source").

We might forbid shebang unless the "--source" option is present.  That
would make it clearer that a non-standard mode is present.  It would be
even more pedantically correct if there were a special "--shebang" mode
(not its real name), leaving "--source" to accept only standard Java
without shebang.

My bottom line suggestions:  allow "java --source any-path" not just
"java --source path.java" and strip shebang in that case; this enables
full-range use of shebang in Unix.  Allow also "java path.java", but
take a moment to reconsider whether shebang makes sense in that
case.

— John


More information about the jdk-dev mailing list