JDK-6304473 : ThreadGroup.uncaughtExceptionHandler doesn't work
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,windows_2000
  • CPU: generic,x86
  • Submitted: 2005-08-01
  • Updated: 2011-01-19
  • Resolved: 2005-08-21
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6
6 b49Fixed
Related Reports
Duplicate :  
Duplicate :  
Relates :  
Description
Run the provided test case.  With 5.0 it will throw an exception and show a modal dialog with the message when it catches it in ThreadGroup.uncaughtExceptionHandler.  With 6.0 this doesn't happen, exception is shown in the console instead.

import javax.swing.*;
import java.awt.*;

public class ExceptionGroup extends ThreadGroup {
  public ExceptionGroup() {
    super("ExceptionGroup");
  }
  public void uncaughtException(Thread t, Throwable e) {
     
      JOptionPane.showMessageDialog(findActiveFrame(),
          e.toString(), "Exception Occurred", JOptionPane.ERROR_MESSAGE);
  
  }
  /**
   * I hate ownerless dialogs.  With this method, we can find the
   * currently visible frame and attach the dialog to that, instead
   * of always attaching it to null.
   */
  private Frame findActiveFrame() {
    Frame[] frames = JFrame.getFrames();
    for (int i = 0; i < frames.length; i++) {
      Frame frame = frames[i];
      if (frame.isVisible()) {
        return frame;
      }
    }
    return null;
  }
}

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

public class Gui extends JFrame {
  private static final int[] DAYS_PER_MONTH =
      {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  public Gui() {
    super("GUI Example");
    final JTextArea text = new JTextArea(14, 30);
    getContentPane().add(new JScrollPane(text));
    getContentPane().add(new JButton(new AbstractAction("Calculate") {
      public void actionPerformed(ActionEvent e) {
          if (SwingUtilities.isEventDispatchThread()) {
              System.out.println("AP in EventDispatchThread()");
              System.out.println("Thread: " + Thread.currentThread());
              System.out.println("TG: " + Thread.currentThread().getThreadGroup());
          }
        text.setText("");
        for (int i=0; i<=DAYS_PER_MONTH.length; i++) {
          text.append("Month " + (i+1) + ": " +
              DAYS_PER_MONTH[i] + "\n");
        }
      }
    }), BorderLayout.NORTH);
  }
  public static void main(String[] args) {
  ThreadGroup exceptionThreadGroup = new ExceptionGroup();
    new Thread(exceptionThreadGroup, "Init thread") {
      public void run() {
        Gui gui = new Gui();
        gui.pack();
        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        gui.show();
      }
    }.start();

  }
}

Comments
SUGGESTED FIX --- EventDispatchThread.java Thu Aug 4 17:53:37 2005 *************** *** 49,54 **** --- 49,58 ---- private boolean doDispatch = true; private static final int ANY_EVENT = -1; + private Vector<EventFilter> eventFilters = new Vector<EventFilter>(); + // used in handleException + private int modalFiltersCount = 0; + EventDispatchThread(ThreadGroup group, String name, EventQueue queue) { super(group, name); theQueue = queue; *************** *** 112,119 **** } } - private Vector<EventFilter> eventFilters = new Vector<EventFilter>(); - public void run() { try { pumpEvents(new Conditional() { --- 116,121 ---- *************** *** 190,195 **** --- 192,198 ---- } } eventFilters.add(k, filter); + modalFiltersCount++; } else { eventFilters.add(filter); } *************** *** 200,205 **** --- 203,211 ---- } } synchronized (eventFilters) { + if (filter instanceof ModalEventFilter) { + modalFiltersCount--; + } eventFilters.remove(filter); } } *************** *** 281,289 **** } // Can get and throw only unchecked exceptions catch (RuntimeException e) { ! processException(e, eventFilters.size() != 0); } catch (Error e) { ! processException(e, eventFilters.size() != 0); } return true; } --- 287,295 ---- } // Can get and throw only unchecked exceptions catch (RuntimeException e) { ! processException(e, modalFiltersCount > 0); } catch (Error e) { ! processException(e, modalFiltersCount > 0); } return true; }
04-08-2005

EVALUATION After the fix for 4080029 (AWT modality umbrella bug) into Mustang b38 all the AWT events are handled on EventDispatchThread using event filters. The old pumpOneEventForHierarchy method is also changed into a special filter. When an exception occured on the EDT, it was handled in latter method for the cases when a modal dialog was shown. When the method was converted into the filter, handling exceptions was also moved into the new method and the condition 'any modal dialog is presented' converted into 'at least one event filter is presented'. But in fact we should take into consideration only those event filters that come from modal dialogs, i. e. instances of ModalEventFilter class. If no such filters are present, no exception handling should be performed in EventDispatchThread class. *** (#1 of 1): [ UNSAVED ] ###@###.###
04-08-2005