繁体   English   中英

Java FX 应用程序中未捕获的异常处理程序将 RuntimeExceptions 捕获为 NullPointerExceptions 的问题

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

我读了这篇文章JavaFx 8 global exception handling并尝试在我的应用程序中处理未捕获的异常。 如帖子中所述,它工作正常。 但是当我添加一个导致 NullPointerException 的语句时,UncaughtExceptionHandler 没有捕获到这个异常。 为什么? 是否有另一个线程处理此异常? 还是我必须设置 DefaultUncaughtExceptionHandler? 我读了JavaDocs:

未捕获的异常处理首先由线程控制,然后由线程的 ThreadGroup object 控制,最后由默认的未捕获异常处理程序控制。 如果线程没有明确的未捕获异常处理程序集,并且线程的线程组(包括父线程组)没有专门化其 uncaughtException 方法,则将调用默认处理程序的 uncaughtException 方法。

我不知道如何获得处理所有未捕获异常的解决方案。 你能帮我吗? 谢谢你的支持!!

这是代码:

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);
    }
    }
}

当我按下按钮时,我在控制台上得到了这个 output:

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

但是当我激活这个语句以获得 NullPointerException

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

我可以在控制台上看到异常没有被捕获,因为缺少语句“MyHandler 捕获异常:” class MyHandler 打印在 Sysout 上。 此外,日志文件上没有写入任何内容。

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

没有答案 - 只是对原因的初步解释(看起来我评论中的第一个想法并不遥远;)

它的基础是应用程序是通过反射实例化的事实:无论在 init/start 中发生的任何异常都会作为实例化中的错误冒泡,即作为 InvocationTargetException。 这些确实由LauncherImpl.launchApplicationWithArgs由... 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;
    }

看不到任何拦截它的方法(这可能是一个错误..或不是)。

编辑

为了实现合并到 InvocationTargetException 的错误的日志记录(除了打印到错误输出),一个选项可能是将 init/start 方法的工作负载包装到try..catch...块中并手动调用处理程序,例如

@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);
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM