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