Imagine this sample java class:
class A { void addListener(Listener obj); void removeListener(Listener obj); } class B { private A a; B() { a = new A(); a.addListener(new Listener() { void listen() {} } }
Do I need to add a finalize method to B to call a.removeListener? Assume that the A instance will be shared with some other objects as well and will outlive the B instance.
I am worried that I might be creating a garbage collector problem here. What is the best practice?
You have a listener variable. So queryRef. removeEventListener(listener) should do the trick.
An event listener in Java is designed to process some kind of event — it "listens" for an event, such as a user's mouse click or a key press, and then it responds accordingly. An event listener must be connected to an event object that defines the event.
SWING Event Listener Interfaces This interface is used for receiving the component events. This interface is used for receiving the item events. This interface is used for receiving the key events.
There is a cycle in the reference graph. A references B and B references A. The garbage collector will detect cycles and see when there are no external references to A and B, and will then collect both.
Attempting to use the finaliser here is wrong. If B is being destroyed, the reference to A is also being removed.
The statement: "Assume that the A instance will be shared with some other objects as well and will outlive the B instance." is wrong. The only way that will happen is if the listener is explicitly removed from somewhere other than a finalizer. If references to A are passed around, that will imply a reference to B, and B will not be garbage collected because there are external references to the A-B cycle.
Further update:
If you want to break the cycle and not require B to explicitly remove the listener, you can use a WeakReference. Something like this:
class A { void addListener(Listener obj); void removeListener(Listener obj); } class B { private static class InnerListener implements Listener { private WeakReference m_owner; private WeakReference m_source; InnerListener(B owner, A source) { m_owner = new WeakReference(owner); m_source = new WeakReference(source); } void listen() { // Handling reentrancy on this function left as an excercise. B b = (B)m_owner.get(); if (b == null) { if (m_source != null) { A a = (A) m_source.get(); if (a != null) { a.removeListener(this); m_source = null; } } return; } ... } } private A a; B() { a = new A(); a.addListener(new InnerListener(this, a)); } }
Could be further generalised if needed across multiple classes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With