/commands/java/run-single-file-source-code
java Hello.java: run a Java source file without javac
- tool
- Java
- versions
- Java 11+ (single file), Java 22+ (multiple files)
- os
- linux, macos, windows
Since Java 11 (JEP 330) you can run a source file directly: java Hello.java compiles it in memory and runs its main method, without creating .class files. Arguments after the file name are passed to the program. Java 22 (JEP 458) extended this to programs made of several source files.
Run a file
cat > Hello.java <<'EOF'
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, " + (args.length > 0 ? args[0] : "world"));
}
}
EOF
java Hello.java
java Hello.java errcodex
ls *.class 2>/dev/null || echo "no .class file written"Output
Hello, world Hello, errcodex no .class file written
Compilation errors
A compile error stops before running, and the exit status is 1:
echo 'public class Bad { public static void main(String[] a) { int x = "text"; } }' > Bad.java
java Bad.javaOutput · exit 1
Bad.java:1: error: incompatible types: String cannot be converted to int
public class Bad { public static void main(String[] a) { int x = "text"; } }
^
1 error
error: compilation failedWhen to use it
Source-file mode suits small tools, teaching examples, quick experiments with a new API and scripts that would otherwise be shell or Python. It saves the separate javac step and keeps the directory free of build output. For anything with several files on Java 11-21, dependencies resolved by a build tool, or code you ship to others, compile with javac (or Maven/Gradle) and run the classes or a JAR instead: the source launcher recompiles the file on every run, which adds start-up time.
The .java extension matters
The launcher only switches to source-file mode when the first argument after the options ends in .java, or when --source is given. Without either, the argument is read as a class name and looked up on the class path:
echo 'public class Hello { public static void main(String[] a) { System.out.println("ran " + a[0]); } }' > Hello.java
cp Hello.java hello
java --source 17 hello script-mode
java helloOutput · exit 1
ran script-mode Error: Could not find or load main class hello Caused by: java.lang.ClassNotFoundException: hello
The first call compiles the extension-less copy because --source 17 forces source-file mode; the second fails because no class named hello exists on the class path.
One file only before Java 22
On Java 11 to 21 the launcher compiles exactly one file. A class defined in a neighbouring .java file is not found, even in the same directory:
echo 'public class Two { public static void main(String[] a) { System.out.println(Util.name()); } }' > Two.java
echo 'class Util { static String name() { return "util"; } }' > Util.java
java Two.javaOutput · exit 1
Two.java:1: error: cannot find symbol
public class Two { public static void main(String[] a) { System.out.println(Util.name()); } }
^
symbol: variable Util
location: class Two
1 error
error: compilation failedOn Java 22 and later (JEP 458) the launcher finds Util.java next to Two.java and compiles it on demand. On older versions, put both classes in one file (only the first top-level class needs main) or compile with javac *.java.
Options
| Option | Effect |
|---|---|
| --source N | Compile the file as Java version N; required when the file name does not end in .java |
| --enable-preview | Allow preview language features (needs --source with the current version) |
| -cp / --class-path | Libraries (JARs or class directories) the source file may use |
| Arguments after the file | Passed to main as args; options for the JVM must come before the file name |
Use it as a script
A file without the .java extension can start with a shebang line, which the launcher ignores:
#!/usr/bin/env -S java --source 17
public class Hello {
public static void main(String[] args) {
System.out.println("Hello from a script");
}
}The -S option of env is needed so java receives --source 17 as a separate argument; it is available in GNU coreutils 8.30+ and on macOS. On Windows there is no shebang support, so run java --source 17 hello instead.
FAQ
Does java Hello.java leave a Hello.class file behind?
No. The source launcher compiles into memory and runs the result; nothing is written to disk. Use javac when you want class files or a JAR to distribute.
Can a source-file program use another .java file in the same folder?
Only from Java 22 (JEP 458). On Java 11 to 21 the launcher compiles just the file you name, so references to other source files fail with cannot find symbol.
Why does java Hello say Could not find or load main class?
Without the .java extension the launcher looks for a compiled class named Hello on the class path. Add the extension, or pass --source N for a file without one.