Saturday, February 10, 2018

Executing Single Java Source Files with One Command

A draft JDK Enhancement Proposal (JEP) was created in late 2017 called "Launch Single-File Source-Code Programs" (its associated JDK issue is JDK-8192920). As its name suggests, this draft JEP aims to "enhance the java launcher to support running a program supplied as a single file of Java source code." In other words, as the JEP describes, if one had a typical self-contained HelloWorld.java source code code file, one could simply run java HelloWorld.java from the command line rather than needing to use javac to compile HelloWorld.java into HelloWorld.class before running it with the java launcher.

JEP owner Jonathan Gibbons summarized this when he introduced the JEP on the compiler-dev mailing list:

This draft JEP contains a proposal to enhance the |java| launcher to support running a program supplied as a single file of Java source code. The program will be compiled and run, without the need to explicit invoke javac, or to package up a jar file.

The primary use cases for such a feature are expected to be for people to run very simple Java applications (the JEP calls them "small utility programs") and people wanting to learn about basic Java features. I have described similar use cases in my blog posts "Learning Java via Simple Tests" and "Compiling and Running Java Without an IDE". The JEP states that in the context of these use cases, "it is pure ceremony to have to compile the program before running it. In addition, a single source file may compile to multiple class files, which adds packaging overhead to the simple goal of 'run this program'. It is desirable to be able to run the program directly from source with the java launcher."

There have been two interesting discussion points on the JDK mailing lists related to this draft JEP. One of the topics discussed is the ability to put a "shebang" on the first line of a Java source code file that is intended to be run in the way this JEP describes (such as used in Groovy and numerous other languages running in Linux/Unix shells). As of this writing, the draft JEP currently addresses this topic under the section heading "Shebang" files and states:

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

#!/path/to/java --source

To allow for such files in source-file mode, if the file begins with #! the contents of the first line up to but not including the first newline are removed before compiling the rest of the file. ... When the file begins with #!, the newline at the end of the first line is preserved so that the line numbers in any error messages remain unchanged.

The second interesting discussion point associated with this draft JEP is the question if its relationship with the jshell introduced with JDK 9. As Brian Goetz states in his message on the compiler-dev mailing list, it is "a natural (and common) thought" to expect that jshell would be used instead of the enhanced java launcher to run these shell-like single source Java source files. Goetz explains in that message why this isn't as good of an idea as it would first seem because jshell was explicitly designed for a "a good interactive experience" rather than as a "batch runner." The current version of the draft JEP addresses this in the Alternatives section, which states:

We could delegate the task of "one-off runs" to the jshell tool. While this may at first seem obvious, this was an explicit non-goal in the design of jshell. The jshell tool was designed to be an interactive shell, and many design decisions were made in favor of providing a better interactive experience. Burdening it with the additional constraints of being the batch runner would detract from the interactive experience.

Although this is only a draft JEP at this point, I like the idea and think it would be a nice minor feature to have added to a future version of the JDK. This feature would allow basic Java examples to be more easily tested by those new to Java and would not burden the novice Java developer with extra steps that he or she is not accustomed to using with some other (often dynamically typed) programming languages. It would also be convenient for more experienced Java developers. I still find myself writing small Java snippets to learn how something works (and to demonstrate to others how it works) and this draft proposed JDK enhancement would make that a bit easier, especially when the Java source file compiles into multiple .class files. This is one of the features I've enjoyed with Groovy development and it'd be nice to have it for simple Java development.

4 comments:

@DustinMarx said...

The draft JEP discussed in this post is now a full-fledged JEP candidate: JEP 330 ("Launch Single-File Source-Code Programs")

@DustinMarx said...

Jonathan Gibbons's message "RFR: 8201274: Launch Single-File Source-Code Programs" on the build-dev mailing list asks for review of "an initial implementation for the feature described in JEP 330: Launch Single-File Source-Code Programs."

@DustinMarx said...

Jonathan Gibbons has provided updated status regarding the implementation of JEP 330. In the post "RFR: 8201274: Launch Single-File Source-Code Programs," Gibbons writes that the latest patch "includes all review feedback so far." Gibbons adds, "The changes are mostly minor, but with the addition of more test cases." The post also mentions that JDK-8201274 ["Launch Single-File Source-Code Programs"] is currently blocked by JDK-8202387 ["javac --release 11 not supported"].

@DustinMarx said...

It was proposed today that JEP 330 be targeted for JDK 11.