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

Memory leak in JOptionPane.createDialog

    Details

    • Subcomponent:
    • Resolved In Build:
      b136
    • CPU:
      x86
    • OS:
      windows_xp
    • Verification:
      Verified

      Description

      FULL PRODUCT VERSION :
      reproduced on 1.4 & 1.5 see below;

      java version "1.5.0_07"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_07-b03
      Java HotSpot(TM) Client VM (build 1.5.0_07-b03, mixed mode, sharing)

      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.2_11-b06)
      Java HotSpot(TM) Client VM (build 1.4.2_11-b06, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      This occurs on any OS

      A DESCRIPTION OF THE PROBLEM :
      Dialogs that are created via createDialog in JOptionPane are never GC'd. The reason for this is because the PropertyChangeListener keeps hold of a reference to the JDialog this method creates.

      The following code references a final variable declared in the method instead of correctly using the event.getSource() as code further up in this method does. This prevents the dialog from being GC'd
      i.e.
          addPropertyChangeListener(new PropertyChangeListener() {
                  public void propertyChange(PropertyChangeEvent event) {
                      // Let the defaultCloseOperation handle the closing
                      // if the user closed the window without selecting a button
                      // (newValue = null in that case). Otherwise, close the dialog.
                      if(dialog.isVisible() && event.getSource() == JOptionPane.this &&
                         (event.getPropertyName().equals(VALUE_PROPERTY)) &&
                          event.getNewValue() != null &&
      event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) {
                          dialog.setVisible(false);
                      }
                  }
              });

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a dialog via JOptionPane, dispose the dialog check your profiler it is still allocated and may cause you to loose a window handle.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Dialog to be disposed
      ACTUAL -
      Dialog is still referenced to the JOptionPane class

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      N/A - no error

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.lang.ref.WeakReference;
      import java.util.ArrayList;
      import java.util.Iterator;

      import javax.swing.JDialog;
      import javax.swing.JOptionPane;

      public class DialogTest {

      public static void main(String args[]) {

      JOptionPane pane = new JOptionPane(null, JOptionPane.UNDEFINED_CONDITION);

      ArrayList references = new ArrayList();
      for (int i=0; i < 10; i++) {
      JDialog dialog = pane.createDialog(null, "Test " + i);
      dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

      {
      // maintain a list of weak references so that
      // we know how many dialog are still allocated post our test
      WeakReference ref = new WeakReference(dialog);
      references.add(ref);
      }
      dialog.dispose(); // force it to close
      System.out.println("Disposing Dialog:" + dialog.hashCode());
      }

      System.out.println("Sleeping to allow for GC");

      // try to free the dialogs, a sleep should only be neccesary but
      // give the GC a chance.
      for (int i=0; i < 100; i++)
      {
      System.gc();
      try {
      Thread.sleep(100);
      } catch (InterruptedException e) {
      e.printStackTrace();
      }
      }

      int originalDialogs = references.size();
      int allocatedCount = 0;

      for (Iterator iter = references.iterator(); iter.hasNext();) {
      WeakReference ref = (WeakReference) iter.next();
      if (ref.get() == null)
      {
      System.out.println("reference is empty bug not reproduced");
      iter.remove(); // if the b
      }
      allocatedCount++;
      System.out.println(ref.get().hashCode() + " is still allocated");
      }
      System.out.println(allocatedCount + " out of [" + originalDialogs + "] are allocated");
      }
      }
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Extend JOptionPane, override the createDialog method, this is not ideal as all classes that use JOptionPane now have to point to a new static class

        Activity

        Show
        tbell Tim Bell added a comment - BT2:EVALUATION Contribution forum : https://jdk-collaboration.dev.java.net/servlets/ProjectForumMessageView?forumID=1463&messageID=15198
        Hide
        rupashka Pavel Porvatov (Inactive) added a comment -
        BT2:EVALUATION

        The PropertyChangeListener that is created in the javax.swing.JOptionPane#initDialog method should be removed while the dialog disposing. The JOptionPane should be removed from the dialog as well.
        Show
        rupashka Pavel Porvatov (Inactive) added a comment - BT2:EVALUATION The PropertyChangeListener that is created in the javax.swing.JOptionPane#initDialog method should be removed while the dialog disposing. The JOptionPane should be removed from the dialog as well.

          People

          • Assignee:
            rupashka Pavel Porvatov (Inactive)
            Reporter:
            ndcosta Nelson Dcosta
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:
              Imported:
              Indexed: