Skip to content

/commands/java/run-single-file-source-code

java Hello.java: run a Java source file without javac

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · openjdk version "17.0.20.1" 2026-08-18updated
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

bash
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:

bash
echo 'public class Bad { public static void main(String[] a) { int x = "text"; } }' > Bad.java
java Bad.java

Output · 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 failed

When 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:

bash
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 hello

Output · 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:

bash
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.java

Output · 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 failed

On 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

OptionEffect
--source NCompile the file as Java version N; required when the file name does not end in .java
--enable-previewAllow preview language features (needs --source with the current version)
-cp / --class-pathLibraries (JARs or class directories) the source file may use
Arguments after the filePassed 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:

hello (chmod +x hello)
#!/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.

Sources