OpenJDK / jdk7u / jdk7u-dev / jdk
changeset 869:b0c557c745e8
6727884: Some Uncaught Exceptions are no longer getting sent to the Uncaught Exception Handlers
Reviewed-by: anthony, dav
author | art |
---|---|
date | Thu, 11 Sep 2008 10:38:00 +0400 |
parents | fd13d8cce933 |
children | 3b9a288d7ddb |
files | src/share/classes/java/awt/EventDispatchThread.java test/java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java |
diffstat | 2 files changed, 142 insertions(+), 106 deletions(-) [+] |
line wrap: on
line diff
--- a/src/share/classes/java/awt/EventDispatchThread.java Wed Sep 10 15:02:06 2008 +0400 +++ b/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); + 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) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/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(); + } +}