I will demonstrate the issue with BooleanProperty, but it applies to other primitive properties as well.
When a BooleanProperty is bound to ObservableValue<Boolean> which is not an ObservableBooleanValue, an intermediate BooleanBinding is created and bound to the underlying ObservableValue<Boolean>. However, when the BooleanProperty is unbound, the intermediate BooleanBinding is not unbound from the underlying ObservableValue<Boolean>, relying on the weak listener. However, this causes a memory leak if the underlying observable value is never invalidated.
This is an instance ofJDK-8095375, but in this particular case it can be resolved by unbinding the intermediate BooleanBinding manually from within BooleanPropertyBase#unbind.
Attached see the test case. The output is
Used Memory after GC: 1.97 MB
Used Memory after GC: 504.11 MB
That is, after 10,000,000 bind()/unbind(), ~500MB of memory is leaked.
When a BooleanProperty is bound to ObservableValue<Boolean> which is not an ObservableBooleanValue, an intermediate BooleanBinding is created and bound to the underlying ObservableValue<Boolean>. However, when the BooleanProperty is unbound, the intermediate BooleanBinding is not unbound from the underlying ObservableValue<Boolean>, relying on the weak listener. However, this causes a memory leak if the underlying observable value is never invalidated.
This is an instance of
Attached see the test case. The output is
Used Memory after GC: 1.97 MB
Used Memory after GC: 504.11 MB
That is, after 10,000,000 bind()/unbind(), ~500MB of memory is leaked.