Первый консьерж, если вы не хотите, чтобы приложение просто взламывало sh и регистрировало причину. Сбой в инициализаторе stati c обычно означает, что со средой что-то серьезно не так, что вы вряд ли сможете восстановить. Кроме того, насколько я знаю, когда класс не загружается, он не может быть снова загружен тем же ClassLoader
.
Тем не менее, если вы хотите показать ошибки своему пользователю в предупреждении , даже если ошибка возникает до инициализации среды выполнения JavaFX, вам нужно где-то сохранить ошибку. Затем, после запуска JavaFX, проверьте, где вы сохранили ошибки, и покажите их. Например:
Main. java:
import javafx.application.Application;
public class Main {
public static void main(String[] args) {
// an "error" before JavaFX is launched
App.notifyUserOfError(new RuntimeException("OOPS!"));
Application.launch(App.class, args);
}
}
Приложение. java:
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayDeque;
import java.util.Objects;
import java.util.Queue;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Label;
import javafx.scene.control.TextArea;
import javafx.scene.layout.Priority;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Font;
import javafx.stage.Stage;
public class App extends Application {
private static Queue<Throwable> errorQueue;
private static App appInstance;
public static synchronized void notifyUserOfError(Throwable throwable) {
Objects.requireNonNull(throwable);
if (appInstance == null) {
if (errorQueue == null) {
errorQueue = new ArrayDeque<>();
}
errorQueue.add(throwable);
} else {
if (Platform.isFxApplicationThread()) {
appInstance.showErrorAlert(throwable);
} else {
Platform.runLater(() -> appInstance.showErrorAlert(throwable));
}
}
}
private static synchronized Queue<Throwable> setAppInstance(App instance) {
if (appInstance != null) {
throw new IllegalStateException();
}
appInstance = instance;
var queue = errorQueue;
errorQueue = null; // no longer needed
return queue;
}
private Stage primaryStage;
@Override
public void start(Stage primaryStage) {
this.primaryStage = primaryStage;
var scene = new Scene(new StackPane(new Label("Hello, World!")), 600, 400);
primaryStage.setScene(scene);
primaryStage.show();
var errors = setAppInstance(this);
if (errors != null) {
// if non-null then should be non-empty
do {
showErrorAlert(errors.remove());
} while (!errors.isEmpty());
// possibly exit the application if you can't recover
}
}
private void showErrorAlert(Throwable error) {
var alert = new Alert(AlertType.ERROR);
alert.initOwner(primaryStage);
alert.setContentText(error.toString());
var sw = new StringWriter();
error.printStackTrace(new PrintWriter(sw));
var area = new TextArea(sw.toString());
area.setEditable(false);
area.setFont(Font.font("Monospaced", 12));
var details = new VBox(5, new Label("Stack trace:"), area);
VBox.setVgrow(area, Priority.ALWAYS);
alert.getDialogPane().setExpandableContent(details);
alert.showAndWait();
}
}
Приведенное выше сообщение помещает ошибку в очередь, если JavaFX имеет еще не инициализирован. В конце метода start
очередь проверяется на наличие ошибок, и они отображаются пользователю один за другим. Если JavaFX уже инициализирован, то ошибка немедленно отображается пользователю.