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

[Beans] Memory Leak in combination with JavaBeanObjectProperty

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P2 P2
    • None
    • 8u5
    • javafx
    • None

      JavaBeanObjectPropertys are not gargabe collected, continuously producing them results in a OutOfMemoryException.

      This minimal setup produces the exception:

      ===============

      import java.beans.PropertyChangeListener;
      import java.beans.PropertyChangeSupport;

      import javafx.beans.property.adapter.JavaBeanObjectProperty;
      import javafx.beans.property.adapter.JavaBeanObjectPropertyBuilder;

      import org.junit.Test;

      public class MemoryLeakTest {

      public class FaceBean {
      private int mouthWidth = 90;
      private final PropertyChangeSupport mPcs = new PropertyChangeSupport(this);

      public int getMouthWidth() {
      return mouthWidth;
      }

      public void setMouthWidth(final int mw) {
      int oldMouthWidth = mouthWidth;
      mouthWidth = mw;
      mPcs.firePropertyChange("mouthWidth", oldMouthWidth, mw);
      }

      public void addPropertyChangeListener(final PropertyChangeListener listener) {
      mPcs.addPropertyChangeListener(listener);
      }

      public void removePropertyChangeListener(final PropertyChangeListener listener) {
      mPcs.removePropertyChangeListener(listener);
      }
      }

      @Test
      @SuppressWarnings({ "unchecked" })
      public void produceMemoryLeak() throws NoSuchMethodException {

      while (true) {
      FaceBean faceBean = new FaceBean();
      JavaBeanObjectPropertyBuilder<?> builder = new JavaBeanObjectPropertyBuilder<>();
      JavaBeanObjectProperty<Integer> mouthWidthProperty = builder.bean(faceBean).name("mouthWidth").build();

      mouthWidthProperty.dispose();
      mouthWidthProperty.unbind();
      }
      }
      }

      ===============


      The problem is in the JavaBeanObjectProperty's constructor. Removing the following part resolves the OutOfMemoryException.

      ===============
      Cleaner.create(this, new Runnable() {
                  @Override
                  public void run() {
                      JavaBeanObjectProperty.this.descriptor.removeListener(listener);
                  }
              });
      ===============

      Inspecting the heap shows that the cleaner never gets collected, holding a reference to the JavaBeanObjectProperty, which ultimately holds a reference to the value object, so it won't be collected either.

            msladecek Martin Sládeček
            mschultejfx Marco Schulte (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported: