9

Here's some code that catches an exception thrown on the Event Dispatch Thread:

package com.ndh.swingjunk;

import java.awt.EventQueue;

import javax.swing.JFrame;

public class EntryPoint {

    public static void main(String[] args) {
        Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler());
//      System.setProperty("sun.awt.exception.handler", MyExceptionHandler.class.getName());

        EventQueue.invokeLater(new Runnable() 
        {
            public void run() 
            {
                new SomeWindow("foo").setVisible(true);
            }
        });
    }
}

class SomeWindow extends JFrame {
    public SomeWindow(String title) {
        this.setTitle(title);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        throw new RuntimeException("hello");
    }
}

I've seen warnings that exceptions thrown on the Event Dispatch Thread don't get handled by the UncaughtExceptionHandler, but that doesn't seem to be the case for my example; it works the same whether the registration line is commented out or left in. Is my example messed up somehow, or is registering the exception handler with the sun.awt.exception.handler no longer necessary?

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276

2 Answers2

17

The EDT class (java.awt.EventDispatchThread, don't look for it in the javadoc, this class is package private) has changed a lot since the origins of AWT.

In JDK6, you can see that this class now can properly handle exceptions occuring inside the EDT. Exception handling is a bit complex in the current version:

  • if you have set the sun.awt.exception.handler property, then your handler will be called for every exception thrown by developer's code called inside the EDT (compatibility with previous JDK versions is ensured).
  • otherwise, any exception will be rethrown, hence will stop the current EDT, and any default UncaughtExceptionHandler will be able to catch it, as your snippet demonstrates.

BUT (and this is very important), if you carefully look at the code of EDT, you'll see that this mechanism won't work if the exception occurs in the EDT while a modal dialog is displayed (I guess this is because EDT and EventQueue management is quite complicated and I would even dare say "messy": a lot of code looks like hacks in there).

In this exact situation, exceptions will be logged to System.err, except if you have set the sun.awt.exception.handler property. Having a default UncaughtExceptionHandler will not help.

So my take on this is that, YES, you should still bother with sun.awt.exception.handler property, except if you can say for sure that your application doesn't use modal dialogs (don't forget that JOptionPane dialogs are also modal).

Urs Reupke
  • 6,791
  • 3
  • 35
  • 49
jfpoilpret
  • 10,449
  • 2
  • 28
  • 32
  • 12
    FYI, this property has been removed in Java7. Modal dialogs now use Thread.UncaughtExceptionHandler correctly: http://bugs.sun.com/view_bug.do?bug_id=6727884 – Gili Jul 09 '11 at 21:40
2

You've called setDefaultUncaughtExceptionHandler instead of setUncaughtExceptionHandler. (If a SecurityManager is present: the former requires RuntimePermission setDefaultUncaughtExceptionHandler; the latter as SecurityManager.checkAccess(Thread).)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • Hawtin I want my JavaFX UI to popup a message box when there is an uncaught error. Can you please clarify which call I should use? – likejudo Jan 16 '13 at 17:43
  • @Anil If it's an untrusted PlugIn/WebStart app it will have to be `setUncaughtExceptionHandler`. In theory I believe you should be using JavaFX only on the event thread, so you'll only need to set it once (but make sure on the right thread). The AWT EDT can exit and be replaced by another thread if there are no realised components, so there's a potential risk that that would not be enough, if that matters. – Tom Hawtin - tackline Jan 16 '13 at 18:22
  • Hawtin JavaFX also uses Tasks and Workers as background threads and I am using them. I dont know if this is 'correct', but here is what I did: In the Controller - UI thread, I called ` Thread.currentThread().setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { OkCancelController okc = null; okc = replaceSceneContent(okc, "ok_cancel.fxml", "App had an error:" + e.getMessage()); } });` – likejudo Jan 16 '13 at 19:41