Consider code like: public class MainClass { public MainClass() { System.out.println("Constructor called!"); } public static void main() { System.out.println("main called!"); } }
and compile and run it, with preview enabled, like: $ javac /tmp/MainClass.java $ java --enable-preview -classpath /tmp MainClass Constructor called! main called! That is wrong, as the `main` method is static, and there is no need to create a new instance of the class. The reason is that as launcher attempts to invoke the main method, it goes in the following order: 1) static-main-with-args; 2) instance-main-with-args; 3) static-main-without-args; 4) instance-main-without-args. But, for the instance variants, the code first creates a new instance of the given class, and only then attempts to lookup the `main` method, and will pass to the next option when the `main` method lookup fails. So, when invoking static-main-without-args, the current class instance may be created for instance-main-with-args, which will then fail due to the missing `main(String[])` method. The proposed solution to this problem is to simply first do a lookup for the `main` method (skipping to the next variant when the given main method does not exist, without instantiating the current class). There is also a relatively closely related problem: what happens when the constructor throws an exception? public class MainClass { public MainClass() { if (true) throw new RuntimeException(); } public void main() { System.out.println("main called!"); } } when compiled an run, this produces no output whatsoever: $ javac /tmp/MainClass.java $ java --enable-preview -classpath /tmp MainClass $ This is because any exceptions thrown from the constructor are effectively ignored, and the launcher will continue with the next variant. This seems wrong - the exception should be printed for the user, like: $ java --enable-preview -classpath /tmp/ MainClass Exception in thread "main" java.lang.RuntimeException at MainClass.<init>(MainClass.java:3) This patch proposes to do that by not consuming the exceptions thrown from the constructor, and stop the propagation to the next variant. ------------- Commit messages: - Updating year. - 8329420: Java 22 (and 23) launcher calls default constructor although main() is static Changes: https://git.openjdk.org/jdk/pull/18753/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=18753&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8329420 Stats: 150 lines in 2 files changed: 130 ins; 4 del; 16 mod Patch: https://git.openjdk.org/jdk/pull/18753.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/18753/head:pull/18753 PR: https://git.openjdk.org/jdk/pull/18753