Java 11: Run Single-File Source Code Programs with java
Introduction
Before Java 11, running even the smallest Java program took two steps - compiling the
(Note - To see how programs were compiled and run before Java 11, read compiling and running Java programs with javac and javaClick to read: compiling and running Java programs with javac and java.) Running a source file with java Let us take a simple program which greets the names passed to it as arguments -
Instead of compiling it first, we pass the source file name, including its
OUTPUT of the above command
What happens behind the scenes
Several classes in one file
The source file can contain more than one top-level class. The launcher runs the first top-level class in the file, so that class must contain the
OUTPUT of the above command
Choosing the source version with --source
By default the source file is compiled for the version of the JDK you are running. The
Running it with
OUTPUT of the above command
Note - The
OUTPUT of the above command
Shebang scripts on Linux and macOS
On Unix-like systems, a single-file Java program can be turned into an executable script, just like a shell or Python script. The first line of the file is a shebang line, which tells the operating system to run the file with
.java file with javac, and then running the .class file with java. Java 11 (JEP 330) lets the java launcher run a single-file source code program directly. This tutorial explains how to run a Java source file with the java command, with examples. We will first run a program and pass it arguments, and see what happens behind the scenes. We will then put several classes in one file, choose the Java version of the source code, and use libraries from the class path. Lastly, we will write a shebang script which runs on Linux and macOS, and go through the limitations of the launcher.(Note - To see how programs were compiled and run before Java 11, read compiling and running Java programs with javac and javaClick to read: compiling and running Java programs with javac and java.) Running a source file with java Let us take a simple program which greets the names passed to it as arguments -
A single-file program
//Greet.java
public class Greet {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("Usage: java Greet.java <name>...");
return;
}
for (String name : args) {
System.out.println("Hello, " + name + "!");
}
}
}
.java extension, to the java command. Everything after the file name is passed to the program as arguments -
java Greet.java Tom Harry
Hello, Tom! Hello, Harry!
- When the file name ends with
.java, the launcher runs in source-file mode. It compiles the file in memory, loads the compiled classes, and runs themainmethod of the first top-level class in the file. - No
.classfile is written to disk. The program is compiled again every time it is run, which adds a little to the startup time. - The command is roughly equivalent to running
javac -d <memory> Greet.javafollowed byjava -cp <memory> Greet Tom Harry. - If the file does not compile, the compilation errors are printed and the program is not run.
javac or a build tool such as Maven or Gradle.
main method. The file name does not need to match the class name -
A source file with several classes
//StudentReport.java
import java.util.List;
public class StudentReport {
public static void main(String[] args) {
List<Student> students = List.of(new Student("Tom", 78), new Student("Harry", 91));
students.forEach(s -> System.out.println(s.name + " -> " + Grader.grade(s.marks)));
}
}
class Student {
final String name;
final int marks;
Student(String name, int marks) {
this.name = name;
this.marks = marks;
}
}
class Grader {
static String grade(int marks) {
return marks >= 90 ? "A" : marks >= 75 ? "B" : "C";
}
}
Tom -> B Harry -> A
--source option compiles it for an older version instead, which is useful to check that a script still works on an older JDK. For example, the program below uses a switch expression, a feature added in Java 14 -
A program using a feature newer than Java 11
//Season.java
public class Season {
public static void main(String[] args) {
int month = 7;
String season = switch (month) {
case 12, 1, 2 -> "Winter";
case 6, 7, 8 -> "Summer";
default -> "Spring or Autumn";
};
System.out.println(season);
}
}
--source 11 fails, because switch expressions did not exist in Java 11 -
java --source 11 Season.java
Season.java:5: error: switch expressions are not supported in -source 11
String season = switch (month) {
^
(use -source 14 or higher to enable switch expressions)
Season.java:6: error: multiple case labels are not supported in -source 11
case 12, 1, 2 -> "Winter";
^
(use -source 14 or higher to enable multiple case labels)
Season.java:6: error: switch rules are not supported in -source 11
case 12, 1, 2 -> "Winter";
^
(use -source 14 or higher to enable switch rules)
3 errors
error: compilation failed
--source option also switches the launcher into source-file mode, so it can be used to run a file whose name does not end in .java. We will use this for shebang scripts below.
Using libraries from the class path
A single-file program can use classes from libraries in the usual way, by putting the library's JAR files or class directories on the class path with -cp. In the example below, TextUtils stands for a library class, which has already been compiled into the classes directory -
A compiled library class
//TextUtils.java
public class TextUtils {
public static String banner(String text) {
String line = "*".repeat(text.length() + 4);
return line + "\n* " + text + " *\n" + line;
}
}
A single-file program which uses the library
//UsesLibrary.java
public class UsesLibrary {
public static void main(String[] args) {
System.out.println(TextUtils.banner("Java 11"));
}
}
java -cp classes UsesLibrary.java
*********** * Java 11 * ***********
java. The launcher ignores this first line when it compiles the file -
A Java shebang script (file name: greet, no extension)
#!/usr/bin/java --source 11
public class Greet {
public static void main(String[] args) {
for (String name : args) {
System.out.println("Hello, " + name + "!");
}
}
}
chmod +x greet ./greet Tom Harry Hello, Tom! Hello, Harry!
- The script file must not have a
.javaextension. A.javafile is expected to be a valid Java source file, which a shebang line is not. Since the name does not end in.java,--sourceis needed in the shebang line to put the launcher in source-file mode. - Use the path of the
javaexecutable on your system in the shebang line. You can find it withwhich java.
- One source file - in Java 11, the program must fit in a single file. Classes in other source files are not compiled, although already compiled classes can be used from the class path. (Java 22, through JEP 458, extended the launcher to compile other source files which the program uses.)
- The first class is run - the first top-level class in the file must have the
mainmethod. - Compiled on every run - nothing is cached, so programs that are run often, or that need a fast startup, should be compiled ahead of time.
- No annotation processing - the in-memory compiler does not run annotation processors, so libraries like Lombok do not work in source-file mode.
java command, which compiles it in memory without writing .class files. We passed arguments to the program, put several classes in one file, compiled for an older Java version with --source, and used library classes from the class path. We then turned a Java program into a shebang script, and lastly went through the limitations of source-file mode. In the next tutorial, we will look at the other API additions in Java 11Click to read tutorial: Java 11 API Additions: Files.readString, Predicate.not, such as Files.readString() and Predicate.not().Continue Reading Java 11 Tutorials
Java 11 API Additions: Files.readString, Predicate.notClick to read tutorial: Java 11 API Additions: Files.readString, Predicate.not Java 11 var in Lambda Parameters with ExamplesClick to read tutorial: Java 11 var in Lambda Parameters with Examples Overview of New Features in Java 11Click to read tutorial: Overview of New Features in Java 11 Java 11 String Methods: isBlank, lines, strip, repeatClick to read tutorial: Java 11 String Methods: isBlank, lines, strip, repeat Java 11 HTTP Client API Tutorial with ExamplesClick to read tutorial: Java 11 HTTP Client API Tutorial with Examples Java 11 Removed Modules: Java EE, CORBA and JavaFXClick to read tutorial: Java 11 Removed Modules: Java EE, CORBA and JavaFX
Java 11 API Additions: Files.readString, Predicate.notClick to read tutorial: Java 11 API Additions: Files.readString, Predicate.not Java 11 var in Lambda Parameters with ExamplesClick to read tutorial: Java 11 var in Lambda Parameters with Examples Overview of New Features in Java 11Click to read tutorial: Overview of New Features in Java 11 Java 11 String Methods: isBlank, lines, strip, repeatClick to read tutorial: Java 11 String Methods: isBlank, lines, strip, repeat Java 11 HTTP Client API Tutorial with ExamplesClick to read tutorial: Java 11 HTTP Client API Tutorial with Examples Java 11 Removed Modules: Java EE, CORBA and JavaFXClick to read tutorial: Java 11 Removed Modules: Java EE, CORBA and JavaFX