12

I tried

Thread.setDefaultUncaughtExceptionHandler...


in the main, and also in the start(Stage primaryStage) method. It ain't working.
I also tried

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


Exception stack trace.

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

Thanks for helping.

jerome
  • 2,029
  • 4
  • 38
  • 58

3 Answers3

17

If you check the code for Platform.runLater() (see below), you will see that the exceptions are swallowed (lines 146 / 147), so a default uncaught exception handler won't be able to catch them - based on that piece of code, I don't think you have any options but to include try/catch blocks in your runnables.

Note that this issue has been reported (requires login - registration is free) and should be fixed in Lombard (= Java FX 8.0 to be released with Java 8 next year).

You could alternatively create a utility method and call

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

Code of 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     }
assylias
  • 321,522
  • 82
  • 660
  • 783
  • sorry, i left the bounty to expire :-(, while i should have given it to this answer. what about putting a new one? – AgostinoX Oct 17 '12 at 15:44
  • @AgostinoX it's happened to me before ;-) You don't have to. – assylias Oct 17 '12 at 15:49
  • Thanks for pointing this out. Your wrapper however will only work with exceptions directly thrown in the Runnable code. For instance, if you set up the Scene in the Runnable, it will catch Exceptions during the Scene build, but NOT exceptions that occurr later, e.g. through events when actually USING the scene... – mmey Feb 16 '13 at 01:31
  • @MartinMeyer Those other exceptions should hopefully be "catchable" (i.e. not swallowed). – assylias Feb 16 '13 at 08:26
  • Same comment as below. Will wrapping work? See the exception in question is in (inner thread now and is till getting gobbled up) so will we get any information of that exception object? Pardon my basic doubt try { r.run(); //extra code } catch (Throwbale t) { t.printStackTrace(); } is the stackTrace is of r? – manocha_ak Jul 24 '14 at 14:00
  • Ohh my goodness! Is start() and run() the difference? Swing and JavaFx do these dirty tricks. And I was thinking I have so many threads :) – manocha_ak Jul 24 '14 at 14:01
2

Some managed threads such as the UI Event Handler and ExecutorServices capture Throwable themselves to avoid the threads dying. Only threads which die will use this UncaughtExceptionHandler. If you want to capture exception thrown you have to do thsi in the method which can throw these exceptions.

If the UI Event Handler has a way of reporting exceptions it will be a different method.

Your second example will catch exception thrown in that thread. Exception thrown on other threads will be catch on that thread.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • What about for NullPointerException ? – jerome Sep 07 '12 at 13:31
  • All Exceptions and Errors are handled the same. – Peter Lawrey Sep 07 '12 at 13:33
  • There should be an elegant solution to your problem. Having a look at the source to see if there is one. ;) – Peter Lawrey Sep 07 '12 at 13:36
  • 1
    In Java 7 setDefaultUncaughtExceptionHandler should work for the EDT thread as well. For Java 6 see this: http://stackoverflow.com/questions/5794472/why-bother-with-setting-the-sun-awt-exception-handler-property – lbalazscs Sep 07 '12 at 13:45
  • I have checked it doesn't work with Java FX 2.2 on Java 7 update 7. – Peter Lawrey Sep 07 '12 at 13:48
  • It would work for Swing, but I don't think it will with JavaFX. – jerome Sep 07 '12 at 13:50
  • I haven't figured out how to get the source for JavaFX 2.2 :| – Peter Lawrey Sep 07 '12 at 14:03
  • I know there is openJFX, but I never tried to download it from there repository. And I'm not sure if they have the full sources. – jerome Sep 07 '12 at 14:54
  • I have tried to download it but it didn't have the source for the core run loop (or at least I couldn't find it) – Peter Lawrey Sep 07 '12 at 14:56
  • Netbeans is able to display the stack trace on the console, so there must be a way to do so in my application also. – jerome Sep 07 '12 at 15:02
  • Netbeans captures the output from System.err. This is difficult to analyse programmatic ally. – Peter Lawrey Sep 07 '12 at 15:05
  • This means that you have to include a try-catch block for each button action handler. This is so much worse than swing. The idea of unchecked exceptions is that they cannot be handled and lead to an unmanageable state. Nevertheless, some sort of last-resort management is usually done(log to disk/email to support). Force developers to handle runtime exceptions in each method means substantially turn them into checked exceptions. Checked and unchecked both have their own advantages and disadvantages, but turning the ones into the others in this case seems to lead to the worst of the two worlds. – AgostinoX Oct 09 '12 at 09:13
  • 2
    I've placed a bounty, because in my opinion this problem requires more attention. Perhaps we actually end up with a different "architecture" for exception management, based on this new "uncatchable" principle, but then samples and explanations are required, because many of us correctly think that setDefaultUncaughtExceptionHandler should work. – AgostinoX Oct 09 '12 at 09:13
  • @AgostinoX And for Swing this change was made so you could use that method suggesting JavaFX should work the same way. – Peter Lawrey Oct 09 '12 at 09:20
  • @Peterl Lawery, i don't understand. Is there a pending request for this implementation? – AgostinoX Oct 09 '12 at 09:26
  • @AgostinoX I think there should be, but I don't know of one. I suggest you submit one to the `java bug database` – Peter Lawrey Oct 09 '12 at 09:28
  • @Peter Lawery: ok. To avoid the question to be dropped immediately, i need it to be well justified. My idea is to say that even if the new model may be accepted, it is undocumented both at tutorial level and in docs. In particular, it should have been stated somewhere that my expectation of setting the default uncaught exception handler for a thread won't work for fx application thread. I have to be sure of this. After i've searched, i found nothing. Have you? – AgostinoX Oct 09 '12 at 09:50
  • @AgostinoX At the very least you are ask that it be made clearer in documentation with examples that this is the preferred approach (or whatever the official approach is) – Peter Lawrey Oct 09 '12 at 10:05
2

Setting the EventDispatcher to the root Node worked for me.

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