Issue with catching RuntimeExceptions as NullPointerExceptions by an uncaught exception handler in Java FX applications

不羁的心 提交于 2021-01-28 19:46:36

问题


I read this post JavaFx 8 global exception handling and tried to handle uncaught exceptions in my application. It works fine as described in the post. But when I added a statement which caused a NullPointerException the UncaughtExceptionHandler did not catch this exception. Why ? Is there another thread handling this exception? Or do I have to set the DefaultUncaughtExceptionHandler? I read JavaDocs:

Uncaught exception handling is controlled first by the thread, then by the thread's ThreadGroup object and finally by the default uncaught exception handler. If the thread does not have an explicit uncaught exception handler set, and the thread's thread group (including parent thread groups) does not specialize its uncaughtException method, then the default handler's uncaughtException method will be invoked.

I have no idea how to get the solution which handles all uncaught exceptions. Can you help? Thanks for your support!!

This is the code:

package TestSimpleDialog;

public class Main extends Application {
    private final Logger logger = Logger.getLogger(this.getClass().getName());
    private MyHandler myHandler = new MyHandler();
    @Override
    public void init() {
    // Thread.currentThread is the FX-Launcher thread:
    Thread.currentThread().setUncaughtExceptionHandler(myHandler);
    System.out.println(Thread.currentThread().getUncaughtExceptionHandler());
    try {
        logger.addHandler(new FileHandler("java.myLOG"));
    }
    catch (IOException e) {
        throw new IllegalStateException("IOException when adding File Handler");
    }
    }
    @Override
    public void start(Stage primaryStage) {
    logger.info("Test Application started");
    // Thread.currentThread() is the FX-Application thread:
    Thread.currentThread().setUncaughtExceptionHandler(myHandler);
    // If this thread has not had an uncaught exception handler explicitly set then this thread's ThreadGroup object
    // is returned, unless this thread has terminated, in which case null is returned.
    System.out.println(Thread.currentThread().getUncaughtExceptionHandler());

    //        try {
    //            URI uriTest = new URI(null);
    //        } catch (URISyntaxException e) {
    //            throw new IllegalStateException("URISyntaxException by testing");
    //        }

    StackPane root = new StackPane();
    Button button = new Button("Throw exception");
    button.setOnAction(event -> {
        throw new RuntimeException("** T E S T **") ;
    });
    root.getChildren().add(button);
    Scene scene = new Scene(root, 150, 60);
    primaryStage.setScene(scene);
    primaryStage.show();
    }

    public static void main(String[] args) {
    launch(args);
    }

    class MyHandler implements Thread.UncaughtExceptionHandler{
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        System.out.println("MyHandler caught exception: "+throwable.getMessage());
        logger.log(Level.SEVERE, "**TEST** threw an uncaught exception", throwable);
    }
    }
}

When I push the button, I have got this output on the console:

TestSimpleDialog.Main$MyHandler@49285759
Aug. 08, 2020 5:55:33 NACHM. TestSimpleDialog.Main start
INFORMATION: Test Application started
TestSimpleDialog.Main$MyHandler@49285759
MyHandler caught exception: ** T E S T **
Aug. 08, 2020 5:55:51 NACHM. TestSimpleDialog.Main$MyHandler uncaughtException
SCHWERWIEGEND: **TEST** threw an uncaught exception
java.lang.RuntimeException: ** T E S T **
    at TestSimpleDialog.Main.lambda$start$0(Main.java:47)
    at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at javafx.base/com.sun.javafx.event.BasicEventDispatcher............

But when I activated this statement to get a NullPointerException

try {
    URI uriTest = new URI(null);
} catch (URISyntaxException e) {
    throw new IllegalStateException("URISyntaxException by testing");
}

I could see on the console that the exception was not caught because of missing the statement "MyHandler caught exception: " the class MyHandler prints on Sysout. Furthermore nothing is written on the logging file.

TestSimpleDialog.Main$MyHandler@22b2aa29
TestSimpleDialog.Main$MyHandler@22b2aa29
Aug. 08, 2020 6:16:51 NACHM. TestSimpleDialog.Main start
INFORMATION: Test Application started
Exception in Application start method
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:566)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    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:566)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.NullPointerException
    at java.base/java.net.URI$Parser.parse(URI.java:3104)
    at java.base/java.net.URI.<init>(URI.java:600)
    at TestSimpleDialog.Main.start(Main.java:41)
    at javafx.graphics/com.sun.javafx.application.............

回答1:


Don't have an answer to how - just a tentative explanation to the why (looks like the first thought in my comments wasn't far off ;)

At its base is the fact that the Application is instantiated via reflection: whatever exceptions happen in init/start bubble up as errors in instantiation, namely as InvocationTargetException. And these are indeed handled by LauncherImpl.launchApplicationWithArgs by .. ex.printStackTrace

public static void launchApplicationWithArgs(final ModuleAccess mainModule,
        final String mainClassName,
        final String preloaderClassName, String[] args) {

  // invoke, handle exception, line 472
  ...
    } catch (InvocationTargetException ex) {
        ex.printStackTrace();
        abort(null, "Exception running application %1$s", tempAppClass.getName());
        return;
    }

Don't see any way to intercept that (which might be a bug .. or not).

Edit

To achieve logging (beyond printing to the error output) of errors coalesced into InvocationTargetException, an option might be to wrap the workload of the init/start method into a try .. catch ... block and manually invoke the handler, something like

@Override
public void init() throws Exception {
    try {
        // do stuff that might be throwing
        throw new ArithmeticException("am I caught?");
    } catch (Exception ex) {
        // invoke the handler and re-throw
        myHandler.uncaughtException(Thread.currentThread(), ex);
        throw(ex);
    }

}


来源:https://stackoverflow.com/questions/63317670/issue-with-catching-runtimeexceptions-as-nullpointerexceptions-by-an-uncaught-ex

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!