Loading... (original) (raw)

Summary

Update the Java launcher to support launching single-file source-code programs.

Problem

(For full details and examples, see JEP 330).

The need to perform separate "compile" and "execute" steps for simple programs makes it harder to learn how to use Java, and harder to deploy simple programs as executable code.

Solution

Update the Java launcher to be able to launch single file programs, by recognizing the use of a source file name on the command line, so that it can be compiled and subsequently executed.

In addition, update the launcher to make it easier to leverage the "shebang" mechanism often found on Unix-derived systems to execute single-file programs.

Discussion

The solution introduces a new --source version option to force source-file mode and/or to specify the version of the source language and API used in the source file. As part of the operation of source-file mode, an implicit --release version option is passed to the internal invocation of the platform compiler, javac.

The javac --release option is closely related to the long-standing javac -source option, and so there is some risk of confusion between the new launcher --source option and the javac-source option, for those who are familiar with the latter.

It has been considered to rename or alias the new launcher --source option as --release, leveraging the analogy with the javac option. However, while a --source option for the launcher can be neatly described as enabling "source-file mode" there is no such easy explanation for --release. Furthermore, introducing --release version as a launcher option might lead users to believe it has an impact on the runtime when it is used, which is definitely not the case.

Additionally, the use of --release as a launcher option, albeit with different semantics, has already been considered and rejected. (See JEP 12.)

Finally, unlike all other options that are supported both by the launcher and by the compiler (including all the path-related options and module system options), the new launcher option is not a direct analog of either the javac -source option or--release option, which significantly reduces the incentive to choose either one for that reason.

The decision is therefore to use --source as the least confusing of the two alternatives.

Specification

The change is a combination of two parts:

  1. An enhancement to the interpretation of what previously has been the "main class" on the command line.
  2. A new --source version option

First, the launcher identifies the first argument (if any) on the command line that is neither an option nor a part of an option ... i.e. the argument that previously has always identified the name of the main class to be invoked.

Then, if that argument identifies an existing file with an extension of .javait is assumed to identify a source file.

Or, if the argument identifies an existing file and a new --source version option is also present on the command line, the argument is assumed to be a source file regardless of the file's extension. The version identifies the language version of the source code in the file.

If either of the preceding conditions identify the argument as a source file, the launcher proceeds in source-file mode as follows:

In source-file mode, any additional command-line options are processed as follows:

In source-file mode, compilation proceeds as follows:

In source-file mode, execution proceeds as follows:

Note that there is a potential minor ambiguity when using a simple command-line like java HelloWorld.java. Previously, HelloWorld.java would have been interpreted as a class called java in a package called HelloWorld, but which is now resolved in favor of a file called HelloWorld.java if such a file exists.

The new --source version option, and the enhanced behavior for determining the main class to be executed, do not affect the VM or JNI interface.

Command-line help

The primary command-line help, generated by --help, is modified as follows:

7a8
>    or  java [options] source-file [args]
9,10c10,12
<  Arguments following the main class, -jar <jarfile>, -m or --module
<  <module>/<mainclass> are passed as the arguments to main class.
---
>  Arguments following the main class, source-file, -jar <jarfile>,
>  -m or --module <module>/<mainclass> are passed as the arguments to
>  main class.

The additional command-line help, generated by --help-extra, is modified as follows:

58a59,60
>     --source <version>
>                       specify the Java language version expected in source-file mode

"Shebang" files

"Shebang" files are a mechanism provided by some Unix-derived systems to execute a file with an executable named in the first line of the file, which must begin with the two ASCII characters #!. Any content on the first line after the name of the executable is typically passed as an initial argument, along with the name of the file, to the nominated executable.

To support this mechanism for Java source files, the source-code launcher makes two accommodations:

  1. When the launcher reads the source file, if the first line begins with ASCII #!, 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.
  2. Some operating systems pass the text on the first line after the name of the executable as a single argument to the executable. With that in mind, if the launcher encounters an option beginning --sourceand containing whitespace, it is split into a series of words, separated by whitespace, before being further analyzed by the launcher.