提交 c8f086e1 编写于 作者: A art

6727884: Some Uncaught Exceptions are no longer getting sent to the Uncaught Exception Handlers

Reviewed-by: anthony, dav
上级 dc423209
......@@ -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) {
......
/*
@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();
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册