6727884: Some Uncaught Exceptions are no longer getting sent to the Uncaught Exception Handlers
Reviewed-by: anthony, dav
--- a/jdk/src/share/classes/java/awt/EventDispatchThread.java Wed Sep 10 15:02:06 2008 +0400
+++ b/jdk/src/share/classes/java/awt/EventDispatchThread.java Thu Sep 11 10:38:00 2008 +0400
@@ -286,119 +286,19 @@
}
// 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);
- }
- 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;
- }
+ eventLog.log(Level.FINE, "Processing exception: " + 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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java Thu Sep 11 10:38:00 2008 +0400
@@ -0,0 +1,136 @@
+/*
+ @test
+ @bug 6304473 6727884
+ @summary Tests that an exception on EDT is handled with ThreadGroup.uncaughtException()
+ @author artem.ananiev: area=awt.eventdispatching
+ @library ../../regtesthelpers
+ @build Util
+ @run main HandleExceptionOnEDT
+*/
+
+import java.awt.*;
+import java.awt.event.*;
+
+import test.java.awt.regtesthelpers.Util;
+
+public class HandleExceptionOnEDT
+{
+ private final static String EXCEPTION_MESSAGE = "A1234567890";
+
+ private static volatile boolean exceptionHandled = false;
+ private static volatile boolean mousePressed = false;
+
+ public static void main(String[] args)
+ {
+ final Thread.UncaughtExceptionHandler eh = new Thread.UncaughtExceptionHandler()
+ {
+ @Override
+ public void uncaughtException(Thread t, Throwable e)
+ {
+ if (e.getMessage().equals(EXCEPTION_MESSAGE))
+ {
+ exceptionHandled = true;
+ }
+ }
+ };
+
+ Frame f = new Frame("F");
+ f.setBounds(100, 100, 400, 300);
+ // set exception handler for EDT
+ f.addWindowListener(new WindowAdapter()
+ {
+ @Override
+ public void windowOpened(WindowEvent we)
+ {
+ Thread edt = Thread.currentThread();
+ edt.setUncaughtExceptionHandler(eh);
+ }
+ });
+ f.setVisible(true);
+
+ Robot r = Util.createRobot();
+ Util.waitForIdle(r);
+
+ // check exception without modal dialog
+ MouseListener exceptionListener = new MouseAdapter()
+ {
+ @Override
+ public void mousePressed(MouseEvent me)
+ {
+ throw new RuntimeException(EXCEPTION_MESSAGE);
+ }
+ };
+ f.addMouseListener(exceptionListener);
+
+ exceptionHandled = false;
+ Point fp = f.getLocationOnScreen();
+ r.mouseMove(fp.x + f.getWidth() / 2, fp.y + f.getHeight() / 2);
+ Util.waitForIdle(r);
+ r.mousePress(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(r);
+ r.mouseRelease(InputEvent.BUTTON2_MASK);
+ f.removeMouseListener(exceptionListener);
+
+ if (!exceptionHandled)
+ {
+ throw new RuntimeException("Test FAILED: exception is not handled for frame");
+ }
+
+ // check exception with modal dialog
+ final Dialog d = new Dialog(f, "D", true);
+ d.setBounds(fp.x + 100, fp.y + 100, 400, 300);
+ d.addMouseListener(exceptionListener);
+ EventQueue.invokeLater(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ d.setVisible(true);
+ }
+ });
+ Util.waitForIdle(r);
+
+ exceptionHandled = false;
+ Point dp = d.getLocationOnScreen();
+ r.mouseMove(dp.x + d.getWidth() / 2, dp.y + d.getHeight() / 2);
+ Util.waitForIdle(r);
+ r.mousePress(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(r);
+ r.mouseRelease(InputEvent.BUTTON2_MASK);
+ d.removeMouseListener(exceptionListener);
+
+ if (!exceptionHandled)
+ {
+ throw new RuntimeException("Test FAILED: exception is not handled for modal dialog");
+ }
+
+ // check the dialog is still modal
+ MouseListener pressedListener = new MouseAdapter()
+ {
+ @Override
+ public void mousePressed(MouseEvent me)
+ {
+ mousePressed = true;
+ }
+ };
+ f.addMouseListener(pressedListener);
+
+ mousePressed = false;
+ r.mouseMove(fp.x + 50, fp.y + 50);
+ Util.waitForIdle(r);
+ r.mousePress(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(r);
+ r.mouseRelease(InputEvent.BUTTON1_MASK);
+ Util.waitForIdle(r);
+ f.removeMouseListener(pressedListener);
+
+ if (mousePressed)
+ {
+ throw new RuntimeException("Test FAILED: modal dialog is not modal or visible after exception");
+ }
+
+ // test is passed
+ d.dispose();
+ f.dispose();
+ }
+}