JDK-4403712 : Error thrown in InvokeAndWait runnable causes hang
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 1.3.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_98
  • CPU: x86
  • Submitted: 2001-01-11
  • Updated: 2017-05-16
  • Resolved: 2003-08-08
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 Availabitlity Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Relates :  
Description

Name: yyT116575			Date: 01/10/2001


java version "1.3.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.0-C)
Java HotSpot(TM) Client VM (build 1.3.0-C, mixed mode)
[Packaged with JBuilder 4]

class Y {
    static {
        System.loadLibrary("abcd"); //lib does not exist.  Throws Error.
    }
}

class X {
    public static void main(String[] args) {
        try {
            javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                public void run()
                {
                    new Y();
                }
            });
        } catch(Exception ex) {
            ex.printStackTrace();
        }
    }
}

Exception occurred during event dispatching:
java.lang.UnsatisfiedLinkError: no acbd in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1312)
	at java.lang.Runtime.loadLibrary0(Runtime.java:749)
	at java.lang.System.loadLibrary(System.java:820)
	at Y.<clinit>(Play.java:10)
	at X$2.run(Play.java:58)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:147)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:317)
	at java.awt.EventDispatchThread.pumpOneEvent
(EventDispatchThread.java:103)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:84)

InvocationEvent needs to catch Throwable instead of Exception.

public class InvocationEvent extends AWTEvent implements ActiveEvent {
    ...
    public void dispatch() {
	if (catchExceptions) {
	    try {
		runnable.run();
	    }
	    catch (Exception e) {   //<== Should be Throwable
		exception = e;
	    }
(Review ID: 114699) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b15
2004-08-24

EVALUATION SwingUtilities.invokeAndWait is forwarded to EventQueue.invokeAndWait. scott.violet@eng 2001-01-16 This is actually an RFE. To change this, we would need to change InvocationEvent so that it would catch throwable instead of exception. New methods would include: public Throwable getThrowable() new ctors that can specify catching throwables as well as exceptions etc. The hang the submitter is describing is actually a duplicate of 4030718 which is fixed in Merlin. eric.hawkes@eng 2001-02-07 Committing to tiger. ###@###.### 2001-11-26 Name: osR10079 Date: 07/30/2003 The following solution for this problem was chosen: Change documentaion for EventQueue.invokeAndWait() to reflect the fact that InvocationTargetException will be thrown if any throwable is thrown when running Runnable. The mechanism currently used to handle Exceptions works through InvocationEvent's constructor with boolean parameter. This parameter specifies whether Exceptions raised during invocation should be caught. The semantics of this parameter should be changed. If it is specified, not only Exceptions, but all other Throwables will be caught and result in InvocationTargetException on the thread that called invokeAndWait(). ###@###.### 2003-07-30 ======================================================================
2003-07-30

SUGGESTED FIX Name: osR10079 Date: 07/30/2003 ------- EventQueue.java ------- *** /tmp/sccs.caa4qv Tue Jul 22 11:39:20 2003 --- EventQueue.java Tue Jul 22 11:27:45 2003 *************** *** 805,811 **** * synchronously on the <code>EventQueue</code> * @exception InterruptedException if another thread has * interrupted this thread ! * @exception InvocationTargetException if an exception is thrown * when running <code>runnable</code> * @see #invokeLater * @since 1.2 --- 805,811 ---- * synchronously on the <code>EventQueue</code> * @exception InterruptedException if another thread has * interrupted this thread ! * @exception InvocationTargetException if an throwable is thrown * when running <code>runnable</code> * @see #invokeLater * @since 1.2 *************** *** 829,837 **** lock.wait(); } ! Exception eventException = event.getException(); ! if (eventException != null) { ! throw new InvocationTargetException(eventException); } } --- 829,837 ---- lock.wait(); } ! Throwable eventThrowable = event.getThrowable(); ! if (eventThrowable != null) { ! throw new InvocationTargetException(eventThrowable); } } ------- InvocationEvent.java ------- *** /tmp/sccs.KYa4dt Tue Jul 22 11:45:24 2003 --- InvocationEvent.java Tue Jul 22 11:30:51 2003 *************** *** 62,69 **** protected Object notifier; /** ! * Set to true if dispatch() catches Exception and stores it in the ! * exception instance variable. If false, Exceptions are propagated up * to the EventDispatchThread's dispatch loop. */ protected boolean catchExceptions; --- 62,69 ---- protected Object notifier; /** ! * Set to true if dispatch() catches Throwable and stores it in the ! * exception instance variable. If false, Throwables are propagated up * to the EventDispatchThread's dispatch loop. */ protected boolean catchExceptions; *************** *** 76,81 **** --- 76,88 ---- private Exception exception = null; /** + * The (potentially null) Throwable thrown during execution of the + * Runnable.run() method. This variable will also be null if a particular + * instance does not catch exceptions. + */ + private Throwable throwable = null; + + /** * The timestamp of when this event occurred. * * @serial *************** *** 116,131 **** * @param notifier the Object whose <code>notifyAll</code> * method will be called after * <code>Runnable.run</code> has returned ! * @param catchExceptions specifies whether <code>dispatch</code> ! * should catch Exception when executing * the <code>Runnable</code>'s <code>run</code> * method, or should instead propagate those ! * Exceptions to the EventDispatchThread's * dispatch loop */ public InvocationEvent(Object source, Runnable runnable, Object notifier, ! boolean catchExceptions) { ! this(source, INVOCATION_DEFAULT, runnable, notifier, catchExceptions); } /** --- 123,138 ---- * @param notifier the Object whose <code>notifyAll</code> * method will be called after * <code>Runnable.run</code> has returned ! * @param catchThrowables specifies whether <code>dispatch</code> ! * should catch Throwable when executing * the <code>Runnable</code>'s <code>run</code> * method, or should instead propagate those ! * Throwables to the EventDispatchThread's * dispatch loop */ public InvocationEvent(Object source, Runnable runnable, Object notifier, ! boolean catchThrowables) { ! this(source, INVOCATION_DEFAULT, runnable, notifier, catchThrowables); } /** *************** *** 145,163 **** * @param notifier the <code>Object whose <code>notifyAll</code> * method will be called after * <code>Runnable.run</code> has returned ! * @param catchExceptions specifies whether <code>dispatch</code> ! * should catch Exception when executing the * <code>Runnable</code>'s <code>run</code> * method, or should instead propagate those ! * Exceptions to the EventDispatchThread's * dispatch loop */ protected InvocationEvent(Object source, int id, Runnable runnable, ! Object notifier, boolean catchExceptions) { super(source, id); this.runnable = runnable; this.notifier = notifier; ! this.catchExceptions = catchExceptions; this.when = System.currentTimeMillis(); } --- 152,170 ---- * @param notifier the <code>Object whose <code>notifyAll</code> * method will be called after * <code>Runnable.run</code> has returned ! * @param catchThrowables specifies whether <code>dispatch</code> ! * should catch Throwable when executing the * <code>Runnable</code>'s <code>run</code> * method, or should instead propagate those ! * Throwables to the EventDispatchThread's * dispatch loop */ protected InvocationEvent(Object source, int id, Runnable runnable, ! Object notifier, boolean catchThrowables) { super(source, id); this.runnable = runnable; this.notifier = notifier; ! this.catchExceptions = catchThrowables; this.when = System.currentTimeMillis(); } *************** *** 170,177 **** try { runnable.run(); } ! catch (Exception e) { ! exception = e; } } else { --- 177,187 ---- try { runnable.run(); } ! catch (Throwable t) { ! if (t instanceof Exception) { ! exception = (Exception) t; ! } ! throwable = t; } } else { *************** *** 197,202 **** --- 207,224 ---- return (catchExceptions) ? exception : null; } + /** + * Returns any Throwable caught while executing the Runnable's <code>run() + * </code> method. + * + * @return A reference to the Throwable if one was thrown; null if no + * Throwable was thrown or if this InvocationEvent does not + * catch Throwables + */ + public Throwable getThrowable() { + return (catchExceptions) ? throwable : null; + } + /** * Returns the timestamp of when this event occurred. * ###@###.### 2003-07-30 ======================================================================
2003-07-30