JavaFX 2 - 捕获所有运行时异常

12

我尝试了

Thread.setDefaultUncaughtExceptionHandler...


我尝试在主要方法和开始方法(Stage primaryStage)中进行编码,但它不起作用。
我还尝试了

public static void main(String[] args) {
 try {
  launch(args);
 }catch(Throwable t) {
  System.out.println(t.getMessage);
 }
}


异常堆栈跟踪。

在javafx.concurrent.Task$TaskCallable$2.run(Task.java:1251) 时 在com.sun.javafx.application.PlatformImpl$3.run(PlatformImpl.java:141) 时 在com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) 时 在com.sun.glass.ui.gtk.GtkApplication$1$1.run(GtkApplication.java:56) 时 在java.lang.Thread.run(Thread.java:662) 时

感谢您的帮助。


你尝试过捕获Throwable吗?它是所有异常类的基类。 - randominstanceOfLivingThing
3个回答

17
如果你查看Platform.runLater()的代码(见下文),你会发现异常被吞掉了(第146/147行),所以默认的未处理异常处理程序无法捕获它们 - 基于这段代码,我认为你没有任何选择,只能在你的运行体中包含try/catch块。
请注意,已报告此问题(需要登录 - 注册是免费的),并应该在Lombard中修复(= Java FX 8.0将在明年与Java 8一起发布)。
或者你可以创建一个实用方法并调用。
Platform.runLater(getFxWrapper(yourRunnable));

public static Runnable getFxWrapper(final Runnable r) {
    return new Runnable() {

        @Override
        public void run() {
            try {
                r.run();
            } catch (Exception e) {
                //here you probably want to log something
                System.out.println("Found an exception");
            }
        }
    };
}

Platform.runLater的代码:


(说明:此链接为英文页面)
  120     private static void runLater(final Runnable r, boolean exiting) {
  121         if (!initialized.get()) {
  122             throw new IllegalStateException("Toolkit not initialized");
  123         }
  124 
  125         pendingRunnables.incrementAndGet();
  126         waitForStart();
  127 
  128         if (SystemProperties.isDebug()) {
  129             Toolkit.getToolkit().pauseCurrentThread();
  130         }
  131 
  132         synchronized (runLaterLock) {
  133             if (!exiting && toolkitExit.get()) {
  134                 // Don't schedule a runnable after we have exited the toolkit
  135                 pendingRunnables.decrementAndGet();
  136                 return;
  137             }
  138 
  139             Toolkit.getToolkit().defer(new Runnable() {
  140                 @Override public void run() {
  141                     try {
  142                         r.run();
  143                         pendingRunnables.decrementAndGet();
  144                         checkIdle();
  145                     } catch (Throwable t) {
  146                         System.err.println("Exception in runnable");
  147                         t.printStackTrace();
  148                     }
  149                 }
  150             });
  151         }
  152     }

抱歉,我让悬赏过期了 :-(,本应该给这个答案的。要不重新发一个? - AgostinoX
@AgostinoX 我以前也遇到过这种情况;-) 你不必这样做。 - assylias
感谢您指出这一点。然而,您的包装器仅适用于在Runnable代码中直接抛出的异常。例如,如果您在Runnable中设置场景,则它将捕获场景构建期间的异常,但不会捕获稍后发生的异常,例如在实际使用场景时通过事件触发的异常... - mmey
@MartinMeyer 希望那些其他的异常可以被“捕获”(即不会被吞噬)。 - assylias
同下方评论。包装会起作用吗?请注意,问题中的异常在(内部线程中)仍在被吞噬,那么我们能获取该异常对象的任何信息吗?请原谅我的基本疑问。尝试 { r.run(); //extra code } catch (Throwbale t) { t.printStackTrace(); } 这个 stackTrace 是 r 的吗? - manocha_ak
哦,我的天啊!start()和run()有什么区别吗?Swing和JavaFx也会玩这些小把戏。我还以为我有很多线程呢 :) - manocha_ak

2

一些托管线程,如UI事件处理程序和ExecutorServices,会自己捕获Throwable以避免线程死亡。只有死亡的线程才会使用此UncaughtExceptionHandler。如果您想捕获抛出的异常,则必须在可能引发这些异常的方法中执行此操作。

如果UI事件处理程序有报告异常的方法,则将使用不同的方法。

您的第二个示例将捕获在该线程中抛出的异常。在其他线程上抛出的异常将在该线程上捕获。


NullPointerException怎么办? - jerome
1
在Java 7中,setDefaultUncaughtExceptionHandler应该也适用于EDT线程。对于Java 6,请参见此链接:https://dev59.com/M1bTa4cB1Zd3GeqP_5bI - lbalazscs
我还没想出如何获取JavaFX 2.2的源代码 :| - Peter Lawrey
这意味着您必须为每个按钮操作处理程序包含一个try-catch块。这比swing糟糕得多。未经检查的异常的想法是它们无法处理并导致无法管理的状态。尽管如此,通常会进行某种最后一道防线的管理(记录到磁盘/发送电子邮件给支持)。强制开发人员在每个方法中处理运行时异常意味着将它们实质上转换为已检查的异常。已检查和未经检查的异常都有各自的优缺点,但在这种情况下将其中之一转换为另一种似乎会导致两种情况中最糟糕的结果。 - AgostinoX
2
我已经设置了赏金,因为我认为这个问题需要更多的关注。也许我们最终会得到一个不同的异常管理“架构”,基于这个新的“无法捕获”的原则,但是我们需要示例和解释,因为我们中的许多人正确地认为setDefaultUncaughtExceptionHandler应该起作用。 - AgostinoX
显示剩余13条评论

2
将EventDispatcher设置为根节点对我很有帮助。
 public class Frame extends Pane {
    Frame() {
        setEventDispatcher(new EventDispatcher() {

            @Override
            public Event dispatchEvent(Event event, EventDispatchChain chain) {
                try {
                    return chain.dispatchEvent(event);
                } catch (final Exception e) {
                    // handle all the exceptions here 
                    return null;
                }
            }
        });
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接