Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4077061

AWT components do not use AWTEventMulticaster in a threadsafe way

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Cannot Reproduce
    • Affects Version/s: 1.1.3, 1.1.8_003
    • Fix Version/s: None
    • Component/s: client-libs
    • Subcomponent:
    • CPU:
      x86
    • OS:
      windows_nt

      Description



      Name: joT67522 Date: 09/05/97


      The code sample in the documentation for java.awt.AWTEventMulticaster
      is not threadsafe. Almost all of the AWT components
      use AWTEventMulticaster in the same manner. If a thread removes the last listener
      as events are being fired, a NullPointerException can be thrown.

      The documented usage sample is this:

       public myComponent extends Component {
           ActionListener actionListener = null;
       
           public void addActionListener(ActionListener l) {
                 actionListener = AWTEventMulticaster.add(actionListener, l);
           }
           public void removeActionListener(ActionListener l) {
         actionListener = AWTEventMulticaster.remove(actionListener, l);
           }
           public void processEvent(AWTEvent e) {
               // when event occurs which causes "action" semantic
               if (actionListener != null) {
                   actionListener.actionPerformed(new ActionEvent());
               }
           }
       }


      In processEvent() another thread could remove the last listener
      after the check for null, resulting in actionPerformed() being called
      on a null pointer. Most AWT components I checked have this same problem
      (e.g. Component, Button, Checkbox, Choice, List etc.)

      Here is a fixed processEvent() sample implementation:

           public void processEvent(AWTEvent e) {
               ActionListener temp = actionListener;
               // when event occurs which causes "action" semantic
               if (temp != null) {
                   temp.actionPerformed(new ActionEvent());
               }
           }


      Here is some sample code which demonstrates the problem
      using a Frame and FocusEvents. One thread continually
      adds and removes a single focus listener from the frame. The other thread
      continually dispatches focus events to the frame.

      After running this sample for a few seconds a NullPointerException
      is thrown:

      java.lang.NullPointerException:
              at java.awt.Component.processFocusEvent(Component.java:1843)
              at java.awt.Component.processEvent(Component.java:1769)
              at java.awt.Container.processEvent(Container.java:792)
              at java.awt.Window.processEvent(Window.java:273)
              at java.awt.Component.dispatchEventImpl(Component.java:1456)
              at java.awt.Container.dispatchEventImpl(Container.java:837)
              at java.awt.Window.dispatchEventImpl(Window.java:401)
              at java.awt.Component.dispatchEvent(Component.java:1393)
              at MulticastTester$3.run(MulticastTester.java:43)
              at java.lang.Thread.run(Thread.java:474)

      I am able to reliably duplicate this using NT 4.0,
      other platforms may or may not show the problem with
      this sample due to different underlying thread
      implementations in the VM.

      Here is the sample code:

      // Test threadsafe usage of AWTEventMulticaster

      import java.awt.*;
      import java.awt.event.*;

      public class MulticastTester {

      public static void main(String args[]) {
      final Frame frame = new Frame("Multicast Tester");
      frame.setSize(300, 300);
      frame.setVisible(true);

      Thread thdListener = new Thread(new Runnable() {
      public void run() {
      boolean bAdd = true;
      FocusListener l = new FocusAdapter() {
      public void focusGained(FocusEvent e) {
      //System.out.println("focusGained");
      }
      };
      while (true) {
      if (bAdd) {
      //System.out.println("addKeyListener");
      frame.addFocusListener(l);
      bAdd = false;
      }
      else {
      //System.out.println("removeKeyListener");
      frame.removeFocusListener(l);
      bAdd = true;
      }
      Thread.yield();
      }
      }
      });
      //thdListener.setPriority(Thread.MAX_PRIORITY);
      thdListener.start();

      Thread thdEvent = new Thread(new Runnable() {
      public void run() {
      FocusEvent evt = new FocusEvent(frame, FocusEvent.FOCUS_GAINED);
      while (true) {
      frame.dispatchEvent(evt);
      //Thread.yield();
      }
      }
      });
      thdEvent.start();
      }
      }
      company - SoftCom , email - ###@###.###
      ======================================================================

        Attachments

          Activity

            People

            • Assignee:
              rraysunw Richard Ray (Inactive)
              Reporter:
              johsunw Joon Oh (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:
                Imported:
                Indexed: