> 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.
Jan Lahoda has updated the pull request incrementally with three additional commits since the last revision: - Reflecting code formatting suggestion. - First lookup the main method, and only then the constructor. - Attempting to solve JDK-8329581 by only ignoring j.l.NoSuchMethodError ------------- Changes: - all: https://git.openjdk.org/jdk/pull/18753/files - new: https://git.openjdk.org/jdk/pull/18753/files/2022aa5a..c007f61e Webrevs: - full: https://webrevs.openjdk.org/?repo=jdk&pr=18753&range=02 - incr: https://webrevs.openjdk.org/?repo=jdk&pr=18753&range=01-02 Stats: 117 lines in 2 files changed: 73 ins; 5 del; 39 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