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

conditionalBinding 'when' the value is itself an observable

XMLWordPrintable

    • generic
    • generic

      ADDITIONAL SYSTEM INFORMATION :
      Windows 11 / Java 17 temurin

      A DESCRIPTION OF THE PROBLEM :
      Conditional bindings created using `when` when bound to a SimpleMapProperty cannot be garbage collectoed because the underlying MapPropertyBase adds a listener to the ObservableMap value which only gets removed when the MapPropertyBase is marked as invalid. This doesn't allow the underlying observable map or mapPropertyBase to be garbage collected since the listener holds a strong reference.

      Normally the listener is removed when the source of the binding is invalidated however since the subscription of the conditional binding was cancelled it will never be updated and thus never marked invalid.

      This is also the case for SimpleSetProperty and SimpleListProperty. It is not clear from the documentation is this is expected behavior for a conditionalBinding when the value is itself an observable.

      If this is intended behavior then it might be nice to have a warning about observables that wrap observables when using the when operator.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Create a MapProperty, bind an active ConditionalBinding of Observable<ObservableMap<>> to it, get the bound property value, set the condition to false.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      The Observable<ObservableMap<<>> is eligible for garbage collection
      ACTUAL -
      The underlying observable map is referenced by the internal mapChangeListener or MapPropertyBase

      ---------- BEGIN SOURCE ----------
      MapProperty<String, String> longLivedMapProperty = new SimpleMapProperty<>();
          ObservableValue<ObservableMap<String, String>> mapSource = new SimpleObjectProperty<>(FXCollections.emptyObservableMap());

          BooleanProperty condition = new SimpleBooleanProperty(true);

          ObservableValue<ObservableMap<String, String>> whenMapProperty = mapSource.when(condition);

          longLivedMapProperty.bind(whenMapProperty);
          longLivedMapProperty.get();

          condition.set(false);
      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      Use an ObjectProperty<ObservableMap<>> or ObjectProperty<Map<>> if possible instead of MapProperty.

      FREQUENCY : always


            jhendrikx John Hendrikx
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated: