Skip to content
Latentism

Java 25: Run Programs Without public static void main

Java 25 lets a program start from a plain void main() in a compact source file. What changed in JEP 512, how it works, and the gotchas, tested on JDK 25.

3 min read

Two code cards. The classic Hello class with public static void main(String[] args) and System.out.println, then the Java 25 compact source file: void main() with IO.println

Since Java 25 you no longer need public static void main(String[] args). A source file can contain just a void main() method, with no class declaration, and the java launcher will run it. The feature is JEP 512, Compact Source Files and Instance Main Methods, final in JDK 25 after four previews (JDK 21 to 24).

The old form still works, and nothing in existing code changes. Everything below was run on OpenJDK 25.0.4.1.

The smallest Java program

Save this as Hello.java:

void main() {
    IO.println("Hello, Java 25");
}

Run it directly, or compile it first:

$ java Hello.java
Hello, Java 25

$ javac Hello.java && java Hello
Hello, Java 25

Three things make this work:

  • A compact source file. Methods and fields at the top level of a file belong to a class the compiler declares for you, named after the file.
  • An instance main method. main no longer has to be public or static, and can drop its String[] parameter.
  • The IO class. java.lang.IO has println, print and readln for simple console programs. Being in java.lang, it needs no import.

Arguments, fields and imports

A compact source file can declare fields and other methods, take arguments, and use any public class in java.base without importing it:

String greeting = "Hello";

void main(String[] args) {
    var names = List.of(args);
    for (String name : names) {
        IO.println(greeting + ", " + name);
    }
}
$ java Greet.java Asha Ravi
Hello, Asha
Hello, Ravi

List worked without import java.util.List, because a compact source file automatically imports the whole java.base module. Reading input is just as short:

void main() {
    String name = IO.readln("Your name: ");
    IO.println("Hi " + name);
}

Instance main in a normal class

Instance main methods aren’t limited to compact files. An ordinary class works too:

class Named {
    void main() {
        System.out.println("instance main in a normal class");
    }
}

The launcher creates an instance with the no-argument constructor, then calls main. If a class has both kinds, the classic one wins:

public class Both {
    public static void main(String[] args) { System.out.println("static main wins"); }
    void main() { System.out.println("instance main"); }
}
$ java Both.java
static main wins

Gotchas we hit

  • println on its own doesn’t compile. In the JDK 23 and 24 previews, IO’s methods were imported automatically. In the final version they’re not, so you must write IO.println. A bare println("...") fails with error: cannot find symbol.
  • JDK 21 to 24 reject it by default. The same Hello.java on JDK 21 fails with unnamed classes are a preview feature and are disabled by default. You need JDK 25, or --enable-preview on an older JDK with that release’s preview syntax.
  • It’s for small programs. The class the compiler declares can’t be referenced by name from other code, so a compact file can’t be part of a larger application. Once a script grows, turn it into a normal class with a package.
  • Your frameworks don’t change. Spring Boot and similar frameworks still start from their own entry points. This feature is about scripts, examples and learning, not production services.

When to use it

Use compact source files for one-off scripts, quick experiments, coding exercises, and teaching Java without explaining public, static and String[] on day one. For anything with more than one file, tests or a build, stick with ordinary classes. They’re still how real Java applications are structured, as in a production-ready Spring Boot REST API.

FAQ

Is public static void main deprecated?

No. It still works in every Java version, and it takes priority when a class has both forms. Java 25 adds a shorter option; it doesn’t remove the old one.

Which Java version do I need?

JDK 25 or later. JDK 21 to 24 had earlier preview versions behind --enable-preview, with slightly different rules, such as IO’s methods being auto-imported.