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

setText causes deadlock in JFormattedTextField, JTextComponent

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P3
    • Resolution: Duplicate
    • Affects Version/s: 1.4.1
    • Fix Version/s: None
    • Component/s: client-libs
    • Labels:

      Description



      Name: jl125535 Date: 11/11/2002


      FULL PRODUCT VERSION :
      java version "1.4.1"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
      Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows XP [Version 5.1.2600]

      ADDITIONAL OPERATING SYSTEMS : Windows 2000 sp2


      A DESCRIPTION OF THE PROBLEM :
      Under certain conditions, the setText(String) method of
      JTextComponent/JFormattedTextField does not appear to be
      thread safe in spite of JDK documentation indicating that
      it is. Deadlock can occur at seemingly random times.

      Because this is a multithreaded, timing dependent, issue
      different hardware platforms may experience different
      results.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Compile and run the demo application.
      2. Click the test button. The application may lock
      immediately or it may lock on a subsequent click.
      3. If it does not lock, you can also try changing the
      timing of the Thread.sleep() methods and/or clicking
      multiple times in succession.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The application should not lock up.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      There are no error messages.

      REPRODUCIBILITY :
      This bug can be reproduced often.

      ---------- BEGIN SOURCE ----------
      /* This class demonstrates that a JFormattedTextField's inherited setText method is not thread-safe. It is also conceivable that JTextComponent's setText method will not be thread-safe even when it is not being
      used as the super class of a JFormattedTextField.

      This class demonstrates thread deadlock occuring when a background thread is attempting to update the JFormattedTextField while the dispatch thread is
      painting. The deadlock evidently arises because the painting thread has acquired the AWTTreeLock before entering AbstractDocument.readLock(). The painting thread waits forever in readLock so that the background thread can finish editing. However, the background thread may call TextComponent.fireCaretUpdate which causes it to hang in subsequent method
      Component.AccessibleAWTComponent.getLocationOnScreen() because the latter needs to synchronize on the AWTTreeLock.
      */

      import javax.swing.*;
      import javax.swing.text.*;
      import javax.accessibility.AccessibleContext;

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


      public class FormattedTextTest extends JFrame {

      private AccessibleContext ac;
      private JFormattedTextField fld;
      private JPanel basePanel;

      private String[] values = new String[]{
      "one, one",
      "two, two",
      "three, three",
      "four, four"};



          public static final void main (String[] args){
              FormattedTextTest t = new FormattedTextTest();
              t.show();
          }
          
      /* Construct a simple dialog to use for a test
      platform. */
      public FormattedTextTest(){
      super();
      setDefaultCloseOperation(DISPOSE_ON_CLOSE);

      JButton testButton = new JButton("Test");
      testButton.addActionListener( new ActionListener(){
      public void actionPerformed(ActionEvent e){
      test();
      }
      });

      fld = new JFormattedTextField();
      fld.setPreferredSize(new Dimension(40, 20));

      /* Similar code is called from BasicComboBoxUI in
      the original application code. It
      causes CaretListeners to be registered. */
      ac = fld.getAccessibleContext();

      /* Installing our own formatter seems to be
      important in this scenario.
      JFormattedTextField may take a different path
      through the code when a formatter has been
      installed.
      */
      DefaultFormatter formatter = new DefaultFormatter();
              DefaultFormatterFactory dff = new DefaultFormatterFactory(formatter);
              fld.setFormatterFactory(dff);

      basePanel = new JPanel();
      basePanel.add(testButton);
      basePanel.add(fld);

      getContentPane().add(basePanel);
      pack();
      }


      /* Launch a background thread to repeatedly modify
      the field. Then use the current (dispatch) thread
      to repeatedly paint the field. */
      private void test(){
      Thread thread = new Thread(new ValueSetter());
      thread.start();

      /* Deadlock occurs when the edit thread and
      the paint thread are in just the right phase
      of execution. A varying timing loop on both
      threads helps to increase the chances of this
      occurring. If it doesn't occur on your
      machine, try adding more loops here
      and/or clicking the button multiple times so that
      multiple background threads will be updating
      the field simultaneously. */
              // Invoking revalidate() and paintImmediately() from the event
              // dispatching thread should be safe.
      for (int n = 0; n < 40; n ++){
      basePanel.revalidate();
      basePanel.paintImmediately(basePanel.getBounds());
      try{
      Thread.sleep(n);
      }
      catch (InterruptedException e){}

      }
      }

      private class ValueSetter implements Runnable{
      public void run(){
      for (int i = 0; i < 10; i++){
      for (int j = 0; j < values.length; j++){

      //this causes deadlock
      fld.setText(values[j]);

      //this alternative appears to be safe
      //fld.setValue(values[j]);

      try{
      Thread.sleep(i + j);
      }
      catch (InterruptedException e){}
      }
      }
      }
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      These *appear* to work but haven't been thoroughly tested.
      1. Don't install Formatter and FormatterFactory.
      2. Use the setValue method instead of the setText method.
      (Review ID: 166755)
      ======================================================================

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                idk Igor Kushnirskiy (Inactive)
                Reporter:
                jleesunw Jon Lee (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: