United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4403712 Error thrown in InvokeAndWait runnable causes hang
JDK-4403712 : Error thrown in InvokeAndWait runnable causes hang

Details
Type:
Enhancement
Submit Date:
2001-01-11
Status:
Resolved
Updated Date:
2003-08-08
Project Name:
JDK
Resolved Date:
2003-08-08
Component:
client-libs
OS:
windows_98
Sub-Component:
java.awt
CPU:
x86
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.3.0
Fixed Versions:
5.0 (tiger)

Related Reports
Relates:

Sub Tasks

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
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
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
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger

FIXED IN:
tiger

INTEGRATED IN:
tiger
tiger-b15


                                     
2004-08-24



Hardware and Software, Engineered to Work Together