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](/_astro/java-25-main-hero.Ba2DCI4W_1EOAR.webp)
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.
mainno longer has to bepublicorstatic, and can drop itsString[]parameter. - The
IOclass.java.lang.IOhasprintln,printandreadlnfor simple console programs. Being injava.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
printlnon 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 writeIO.println. A bareprintln("...")fails witherror: cannot find symbol.- JDK 21 to 24 reject it by default. The same
Hello.javaon JDK 21 fails withunnamed classes are a preview feature and are disabled by default. You need JDK 25, or--enable-previewon 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.



