WeakXXListener - when not to use?

Kevin Rushforth kevin.rushforth at oracle.com
Wed Mar 25 16:25:35 UTC 2020


Here are my quick thoughts on the things to watch out for when 
converting a (strong) listener to a WeakListener, but I would love to 
hear from others.

The main thing you need to do is make sure that the listener doesn't go 
out of scope, and thus become subject to garbage collection, too soon.

At a minimum, it means that the object that creates the listener needs 
to hold a strong reference to the listener. In the case of the two PRs 
referred to above, that minimum bar was cleared (good). By way of 
example, blindly turning the following into a WeakReference would lead 
to a listener almost certainly being released too early:

Before:
     class SomeClass {
         ...
         void someMethod() {
             someOtherObject.addListener((o, oldVal, newVal) -> 
doSomethingUseful(o, oldVal, newVal));
         }
     }

After (wrong) :
     class SomeClass {
         ...
         void someMethod() {
             someOtherObject.addListener(new WeakChangeListener(
(o, oldVal, newVal) -> doSomethingUseful(o, oldVal, newVal)));
         }
     }

So at a minimum, it would need to do this:

After (better) :
     class SomeClass {
         ...
         // hold listener in an instance variable
         private ChangeListener myListener = (o, oldVal, newVal) -> 
doSomethingUseful(o, oldVal, newVal);

         void someMethod() {
             someOtherObject.addListener(new 
WeakChangeListener(myListener));
         }
     }

As for whether the above is sufficient, it depends on what the listener 
does (what its purpose is).In this simple example, it seems unlikely 
that removing the listener when the instance of SomeClass goes out of 
scope will cause any problems. It's worth looking at what 
"doSomethingUseful" does to see if unregisters anything that ought to be 
unregistered (and now maybe won't be if the listener goes away early).

Bringing this back to the two cases in question, I think they are both 
fine, although I pointed Ambarish at one thing to look at in the 
ButtonSkin case (I don't see anything similar for your ChoiceBox leak 
fix that ought to be looked at more carefully).

-- Kevin


On 3/25/2020 3:13 AM, Jeanette Winzenburg wrote:
>
> Currently, there are two open pull requests (#147 and #148) for fixing 
> memory leaks in controls/skin with the same comment from Kevin:
>
> "Using a WeakListener is certainly easier, but runs the risk of the 
> listener being removed too early and not cleaning up after itself."
>
> Looks like I can't come up with a scenario where this might happen - 
> as long as the owner (f.i. a control) of the instance that mananges 
> the listener (f.i. a selectionModel) on a property of the owner keeps 
> a strong reference to the manager.
>
> Questions:
>
> - what to watch out for to safely exlude any unwanted self-removal?
> - how to test?
>
> -- Jeanette
>



More information about the openjfx-dev mailing list