JDK 25 |
---|
25Resolved |
Causes :
|
|
Duplicate :
|
|
Duplicate :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
|
Relates :
|
Consider the following two trivial java files: Foo.java: public class Foo { public static void main(final String[] args) throws Exception { System.out.println("hello world"); } // never invoked or referenced (dead) code private SomeNonExistentRuntimeType doNothing() throws Exception { return null; } } SomeNonExistentRuntimeType.java: public class SomeNonExistentRuntimeType { } Compile them as follows: javac Foo.java SomeNonExistentRuntimeType.java Now delete (only) the compiled SomeNonExistentRuntimeType.class file to simulate the case where that class is missing at runtime (in the classpath). Now run: java Foo This will rightly print: hello world and the program exits normally. Now, using a JDK which has "Instance Main Methods" preview feature, like JDK 23, 24 or mainline, --enable-preview and run the same program again: java --enable-preview Foo This results in the application failing to launch with the following exception: Error: Unable to initialize main class Foo Caused by: java.lang.NoClassDefFoundError: SomeNonExistentRuntimeType This is due to the current implementation of the launcher where, to support JEP-495 https://openjdk.org/jeps/495, it tries to identify potential "main" methods and while doing so it ends up using the existing reflection based infrastructure where it iterates over each method of the main class and tries to resolve the types of the method params and return types, thus resulting in additional classloading and potential classloading failures of non-existent types (that may be unused by the application at runtime). I think the launcher's implementation can be changed to minimize the methods it looks for (it just needs to look for methods named "main") and only resolve the referenced types if that "main" method is determined as the one to invoke.
|