Skip to content
This repository has been archived by the owner on Jun 24, 2021. It is now read-only.

JDK-8230119: NullPointerException if Application subclass has non-static main(String[]) method #570

Open
tkslaw opened this issue Aug 23, 2019 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@tkslaw
Copy link

tkslaw commented Aug 23, 2019

When using the below as a main-class:

import javafx.application.Application;
import javafx.stage.Stage;

public class App extends Application {

    @Override
    public void start(Stage primaryStage) {
        throw new AssertionError("Failed to reproduce NPE.");
    }

    // non-static
    public void main(String[] args) {
        Application.launch(args);
    }

}

The following exception is thrown:

Exception in thread "main" java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.NullPointerException
	at java.base/java.lang.reflect.Method.invoke(Method.java:560)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
	... 5 more

Which is caused by LauncherImpl calling mainMethod.invoke(null, new Object[]{args}), which is just assuming the main method it found is static.


While I doubt such a situation arises often, it came up recently in a question on Stack Overflow. The issue here is the error message does not make the cause obvious. It'd be beneficial if LauncherImpl checked whether or not the method is static and, if it's not, throw a more detailed exception. For example:

if (!Modifier.isStatic(mainMethod.getModifiers()) {
    throw new RuntimeException(mainMethod + " must be static");
}
mainMethod.invoke(null, (Object) args);
@nlisker nlisker added the bug Something isn't working label Aug 23, 2019
@kevinrushforth
Copy link
Collaborator

kevinrushforth commented Aug 23, 2019

In this case we shouldn't throw an exception, but we should ignore that main method and launch the Application in the same manner as if the main method were not there at all.

@tkslaw
Copy link
Author

tkslaw commented Aug 24, 2019

My assumption was that a non-static main method in an Application subclass being used as the main-class is obviously a mistake on the programmer's part, thus the detailed exception. However, I'm happy to consider that assumption incorrect (e.g. because the method may be legitimate). My only worry is ignoring the method altogether might hide the issue where the method is supposed to be static but isn't.

@nlisker
Copy link

nlisker commented Aug 24, 2019

ignoring the method altogether might hide the issue where the method is supposed to be static but isn't.

I agree. Maybe a warning should be emitted.

@kevinrushforth
Copy link
Collaborator

That's a fair point about emitting a warning, since it is likely a mistake. Similarly, if the main method is not public, a warning seems a good idea. I would only want to emit a warning if the signature matches, meaning void main(String[] args) would emit a warning, but void main() would be ignored, since it isn't the same method.

One thing to point out, which might help inform what we want to do here, is that during the review of the launcher test changes needed as part of decoupling of JavaFX from the JDK, the JDK team raised the question of whether the Java launcher support for launching JavaFX Application classes without a main method should be deprecated and removed in a future version. If that is the route we end up going, then a public static void main(String[]) method would be required or else an error would occur. I think that also suggests that a warning is better than silently ignoring it.

@tkslaw
Copy link
Author

tkslaw commented Aug 24, 2019

I agree a warning seems the best option.

Also, if the launching-without-main-method functionality does get deprecated then a warning should be emitted if the main-class is missing the public static void main(String[]) method, saying something like "main method will be required in a future release". To be honest, I was surprised the functionality remained after JavaFX was decoupled from the JDK.

@kevinrushforth
Copy link
Collaborator

if the launching-without-main-method functionality does get deprecated then a warning should be emitted if the main-class is missing the public static void main(String[]) method, saying something like "main method will be required in a future release".

Yes, something along those lines was exactly my thinking.

To be honest, I was surprised the functionality remained after JavaFX was decoupled from the JDK.

It only stayed in because I successfully argued that it would be too disruptive to remove it with no warning and potentially break existing applications. This reminds me that I was supposed to file an RFE to deprecate and then remove it, but haven't done so yet.

@kevinrushforth
Copy link
Collaborator

I filed JDK-8230119 in JBS to track this.

@kevinrushforth kevinrushforth changed the title NullPointerException thrown when Application subclass has a non-static main(String[]) method JDK-8230119: NullPointerException if Application subclass has non-static main(String[]) method Aug 24, 2019
@kevinrushforth
Copy link
Collaborator

Worth noting is that a non-public static void main(String[]) method is silently ignored today. As I mentioned above, when/if we fix JDK-8230119, I think we should emit a warning in that case as well.

@kevinrushforth kevinrushforth self-assigned this Aug 24, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants