On Wed, 17 Apr 2024 06:34:25 GMT, Jan Lahoda <jlah...@openjdk.org> wrote:

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

src/java.base/share/native/libjli/java.c line 477:

> 475:         // and don't continue with the next variant;
> 476:         // leave any exception pending, so that it is visible to the 
> caller:
> 477:         return 1;

Hello Jan, the comment says "don't continue", yet this returns `1` which 
represents "continue". Should this return `0` instead?

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/18753#discussion_r1568470228

Reply via email to