-
Bug
-
Resolution: Fixed
-
P3
-
jfx11
The api doc/signature, from Styleable:
/**
* Return the pseudo-class state of this Styleable. CSS assumes this set is read-only.
* @return the pseudo-class state
*/
ObservableSet<PseudoClass> getPseudoClassStates();
Note that it's observable, so client code can assume that it can install a listener simply like:
// instance fields
SetChangeListener myListener = ...
Node node = ...
private void someInit() {
node.getPseudoClassStates().addListener(myListener);
...
}
Which fails: at some time after init, the notification stops. Reason is that Node returns an ummodifiable wrapper around the states (which is fine) that's recreated on-the-fly on each call (which is a bug, because the returned set has no strong reference and can be garbage collected, see https://stackoverflow.com/q/53580773/203657)
Here's a simple test that fails:
@Test
public void testPseudoStateGarbageCollection() {
// any node will do ..
TableView table = new TableView();
assertSame("must return the same instance on every call",
table.getPseudoClassStates(), table.getPseudoClassStates());
}
A workaround is to keep a strong reference to the set in client code. Ideally, that should happen in Node (just as TableView.getVisibleLeafColumns does) - subclasses can't because the method is final. At the very least the unexpected behavior must be strongly documented.
/**
* Return the pseudo-class state of this Styleable. CSS assumes this set is read-only.
* @return the pseudo-class state
*/
ObservableSet<PseudoClass> getPseudoClassStates();
Note that it's observable, so client code can assume that it can install a listener simply like:
// instance fields
SetChangeListener myListener = ...
Node node = ...
private void someInit() {
node.getPseudoClassStates().addListener(myListener);
...
}
Which fails: at some time after init, the notification stops. Reason is that Node returns an ummodifiable wrapper around the states (which is fine) that's recreated on-the-fly on each call (which is a bug, because the returned set has no strong reference and can be garbage collected, see https://stackoverflow.com/q/53580773/203657)
Here's a simple test that fails:
@Test
public void testPseudoStateGarbageCollection() {
// any node will do ..
TableView table = new TableView();
assertSame("must return the same instance on every call",
table.getPseudoClassStates(), table.getPseudoClassStates());
}
A workaround is to keep a strong reference to the set in client code. Ideally, that should happen in Node (just as TableView.getVisibleLeafColumns does) - subclasses can't because the method is final. At the very least the unexpected behavior must be strongly documented.
- duplicates
-
JDK-8229479 Listeners added to Node.getPseudoClassStates() will suddenly stop receiving
- Closed