java - 如何创建使用 JavaFX 的默认异常处理程序?

标签 java javafx

在我的 JavaFX 应用程序中,我想创建一个全局未捕获异常处理程序,它创建一个显示错误消息和异常堆栈跟踪的对话窗口,然后终止。我正在使用 Thread.setDefaultUncaughtExceptionHandler() 并在其中创建对话框,但异常处理程序中的代码本身会在调用时不断抛出异常。

原因是当JavaFX 应用程序线程中抛出任何未捕获的异常时,JVM 会终止该线程。并且 JavaFX 线程必须正在运行以创建 JavaFX 组件 - 因此无法在异常处理程序中创建类似的对话框......所以我的问题是最好的方法是什么?我想在发生未捕获的异常时向用户显示一条消息,而不是让应用程序突然终止。

这是我一直在使用的:

public void start(Stage primaryStage) throws IOException {
    Thread.setDefaultUncaughtExceptionHandler((Thread t, Throwable e) -> {
        Dialogs.create().title("Error")
            .message("An uncaught exception was thrown in thread \"" + t
                    + "\". Click below to view the stacktrace, or close this "
                    + "dialog to terminate the application.")
            .style(DialogStyle.NATIVE)
            .showExceptionInNewWindow(e);
        Platform.exit();
    });

    primaryStage.show();
    method();
}

public void method() throws IOException {
    //Performs file i/o operations and throws IOException if an error occurs
    throw new IOException();
}

程序后面也可能抛出更多的异常。 (顺便说一句,我正在使用 ControlsFX 库创建对话框窗口。)这是我在运行代码时收到的错误消息:

Exception in Application start method

Exception: java.lang.IllegalStateException thrown from the UncaughtExceptionHandler in thread "main"

最佳答案

认为这里发生的是start() 方法中抛出的异常被调用该方法的代码捕获。因此,start() 方法中抛出的任何内容都不会由您的异常处理程序处理(这不是未捕获 异常)。

但是,在 start() 方法完成后抛出的异常将由您的异常处理程序处理。

但是请注意,异常将在抛出它们的线程中处理。因此,只要在 FX 应用程序线程上抛出这些异常,您的代码就会工作,但不适用于在后台线程中抛出的异常(因为您无法在后台线程中创建和显示对话框)。

为了涵盖所有可能发生的情况:

  1. 如果可能在 start() 方法中抛出异常或错误,请将该代码放在 try - catch 中按常规方式拦截和处理。
  2. 设置默认 未捕获异常处理程序以调用代码以使用Platform.runLater() 显示对话框。这将处理在 FX 应用程序线程外抛出的异常。
  3. 在 FX 应用程序线程上设置未捕获的异常处理程序以调用代码以直接显示对话框。

示例(在 start() 方法中以 50% 的概率抛出错误):

import java.io.IOException;
import java.util.Random;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

import org.controlsfx.dialog.Dialogs;
import org.controlsfx.dialog.DialogStyle;

public class UncaughtExceptionHandlerExample extends Application {

    @Override
    public void start(Stage primaryStage)  {

        Thread.setDefaultUncaughtExceptionHandler((t, e) -> Platform.runLater(() -> showErrorDialog(t, e)));
        Thread.currentThread().setUncaughtExceptionHandler(this::showErrorDialog);

        try {
            Button button = new Button("Create error");
            button.setOnAction(event ->  {
                throw new Error("Boom!");
            });

            Button backgroundErrorButton = new Button("Create error in background thread");
            backgroundErrorButton.setOnAction(event -> {
                new Thread(() -> {
                    throw new Error("Boom");
                }).start();
            });
            HBox root = new HBox(5, button, backgroundErrorButton);
            Scene scene = new Scene(root, 400, 80);
            primaryStage.setScene(scene);
            primaryStage.show();

            if (new Random().nextDouble() < 0.5) {
                throw new Error("Boom");
            }
        } catch (Throwable t) {
            showErrorDialog(Thread.currentThread(), t);
        }
    }

    private void showErrorDialog(Thread t, Throwable e) {
        Dialogs.create().title("Error")
        .message("An uncaught exception was thrown in thread " + t
                + ". Click below to view the stacktrace, or close this "
                + "dialog to terminate the application.")
        .style(DialogStyle.NATIVE)
        .showExceptionInNewWindow(e);
      Platform.exit();
    }

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

顺便说一句,我不认为 JVM 会在 FX 应用程序线程发生未捕获的异常时终止它。

关于java - 如何创建使用 JavaFX 的默认异常处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25145956/

相关文章:

java - 动态更改对讲语言?

java - Intellij 结构搜索和替换所有形式的 if 语句

java - 内容重绘缓慢的滚动合成看起来很难看

java - 无法解析,FomatStyle

java - 如何检测鼠标点击二次曲线的 "stroke"部分?

java - 如何在 JavaFX 中删除标签?

qt - Qt 和 JavaFX 等硬件加速工具包如何实现高质量字体渲染?

java - com.jcraft.jsch.ChannelSftp.get(String src,String dst) 会覆盖现有文件吗?

java - 在 Linux 上创建 JPackage 安装程序 Java 应用程序时,linux-menu-group 应该是什么?

关于 Action 的 Javafx fxml