JDK-6727884 : Some Uncaught Exceptions are no longer getting sent to the Uncaught Exception Handlers
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u7,6u10,7
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2008-07-21
  • Updated: 2011-03-07
  • Resolved: 2011-03-07
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 7
7 b48Fixed
Related Reports
Duplicate :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
J2SE Version (please include all output from java -version flag):
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)

Does this problem occur on J2SE 5.0.x or 6.0?  Yes / No (pick one)
Yes

Operating System Configuration Information (be specific):
Microsoft Windows XP [Version 5.1.2600]

Bug Description:
Regression: Some Uncaught Exceptions are no longer getting sent to the Uncaught Exception Handlers

In 1.4(merlin-beta) problem 4063022 was addressed such that the Uncaught Exceptions 
would be sent to the Uncaught Exception Handlers

In 1.4(merlin-beta3) due to report 4499199 this was broken again such that during 
a modal dialog Uncaught Exceptions would not be sent to the Uncaught Exception Handlers

The EventDispatchThread.processException makes note of this and states that: It may be
useful to add either a runtime flag or API later if someone would like to instead
dispose the dialog and allow the thread group to handle it.

However all the bugs relating to this seem to have been closed as fixed even though 
this problem still exists in 1.6.0_07.

The fix should be very simple replace the EventDispatchThread.processException code 
with this:

Thread thread = Thread.currentThread();
thread.getUncaughtExceptionHandler().uncaughtException(thread, e);

And change the UncaughtExceptionHandler JavaDoc slightly as in this case the Thread 
wont be terminated.

It is not clear why one Event Queue Thread would be terminated and then another one
started doing the same thing when not isModal (the problematic event has already been
removed from the queue), however if there really is a need for this then just the if
(isModal) section of EventDispatchThread.processException can be replaced with the 
above code.

Comments
SUGGESTED FIX diff -r 99658a8d42fa src/share/classes/java/awt/EventDispatchThread.java --- src/share/classes/java/awt/EventDispatchThread.java Thu Aug 14 12:58:51 2008 +0400 +++ src/share/classes/java/awt/EventDispatchThread.java Mon Aug 25 15:55:58 2008 +0400 @@ -286,119 +286,19 @@ class EventDispatchThread extends Thread } // Can get and throw only unchecked exceptions catch (RuntimeException e) { - processException(e, modalFiltersCount > 0); + processException(e); } catch (Error e) { - processException(e, modalFiltersCount > 0); + processException(e); } return true; } - private void processException(Throwable e, boolean isModal) { + private void processException(Throwable e) { if (eventLog.isLoggable(Level.FINE)) { - eventLog.log(Level.FINE, "Processing exception: " + e + - ", isModal = " + isModal); + eventLog.log(Level.FINE, "Processing exception: " + e); } - if (!handleException(e)) { - // See bug ID 4499199. - // If we are in a modal dialog, we cannot throw - // an exception for the ThreadGroup to handle (as added - // in RFE 4063022). If we did, the message pump of - // the modal dialog would be interrupted. - // We instead choose to handle the exception ourselves. - // It may be useful to add either a runtime flag or API - // later if someone would like to instead dispose the - // dialog and allow the thread group to handle it. - if (isModal) { - System.err.println( - "Exception occurred during event dispatching:"); - e.printStackTrace(); - } else if (e instanceof RuntimeException) { - throw (RuntimeException)e; - } else if (e instanceof Error) { - throw (Error)e; - } - } - } - - private static final String handlerPropName = "sun.awt.exception.handler"; - private static String handlerClassName = null; - private static String NO_HANDLER = new String(); - - /** - * Handles an exception thrown in the event-dispatch thread. - * - * <p> If the system property "sun.awt.exception.handler" is defined, then - * when this method is invoked it will attempt to do the following: - * - * <ol> - * <li> Load the class named by the value of that property, using the - * current thread's context class loader, - * <li> Instantiate that class using its zero-argument constructor, - * <li> Find the resulting handler object's <tt>public void handle</tt> - * method, which should take a single argument of type - * <tt>Throwable</tt>, and - * <li> Invoke the handler's <tt>handle</tt> method, passing it the - * <tt>thrown</tt> argument that was passed to this method. - * </ol> - * - * If any of the first three steps fail then this method will return - * <tt>false</tt> and all following invocations of this method will return - * <tt>false</tt> immediately. An exception thrown by the handler object's - * <tt>handle</tt> will be caught, and will cause this method to return - * <tt>false</tt>. If the handler's <tt>handle</tt> method is successfully - * invoked, then this method will return <tt>true</tt>. This method will - * never throw any sort of exception. - * - * <p> <i>Note:</i> This method is a temporary hack to work around the - * absence of a real API that provides the ability to replace the - * event-dispatch thread. The magic "sun.awt.exception.handler" property - * <i>will be removed</i> in a future release. - * - * @param thrown The Throwable that was thrown in the event-dispatch - * thread - * - * @return <tt>false</tt> if any of the above steps failed, otherwise - * <tt>true</tt> - */ - private boolean handleException(Throwable thrown) { - - try { - - if (handlerClassName == NO_HANDLER) { - return false; /* Already tried, and failed */ - } - - /* Look up the class name */ - if (handlerClassName == null) { - handlerClassName = ((String) AccessController.doPrivileged( - new GetPropertyAction(handlerPropName))); - if (handlerClassName == null) { - handlerClassName = NO_HANDLER; /* Do not try this again */ - return false; - } - } - - /* Load the class, instantiate it, and find its handle method */ - Method m; - Object h; - try { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Class c = Class.forName(handlerClassName, true, cl); - m = c.getMethod("handle", new Class[] { Throwable.class }); - h = c.newInstance(); - } catch (Throwable x) { - handlerClassName = NO_HANDLER; /* Do not try this again */ - return false; - } - - /* Finally, invoke the handler */ - m.invoke(h, new Object[] { thrown }); - - } catch (Throwable x) { - return false; - } - - return true; + getUncaughtExceptionHandler().uncaughtException(this, e); + // don't rethrow the exception to avoid EDT recreation } boolean isDispatching(EventQueue eq) {
25-08-2008

EVALUATION I'd suggest the fix to cover two problems with the code: 1. All the EDT exceptions are handled with a custom handler defined by sun.awt.exception.handler property. This looks like an attempt to reinvent the wheel: there is a standard way to handle all the uncaught exceptions in Thread and ThreadGroup classes. 2. AWT Behavior is inconsistent when any modal dialog is shown or not. This also looks odd, so I'd suggest to use Thread.UncaughtExceptionHandler regardless of modal dialogs being shown. Another benefit of this approach is that EDT is not destroyed and recreated too often, this may be useful for all the applications relying on single-threaded model (in fact, all the Swing-based apps).
25-08-2008