In other words, if one of our objects register's with a listener, do
we need to manually remove it from that listener when we want to
completely dispose of that object?
Thanks!
Brett
Yes.
> Thanks!
> Brett
With this discussion in mind, why isn't it common practice to use
WeakReferences within listener-lists?
Cheers
Bent D
--
Bent Dalager - b...@pvv.org - http://www.pvv.org/~bcd
powered by emacs
Let say that an object is 'registered' with a listener that uses a list of
weak references internally, instead of a list of references to the objects.
Presumably, this would alleviate the need for a 'deregistration' on part of
the client who registered the object with the listener. Now, being a weak
reference will not prevent the object from being considered for reclamation
by the garbage collector. So if one does nothing else in the listener, the
behavior of the listener would not be the same under all circumstances.
Objects that were registered could be 'lost' under low memory conditions if
their only reference were in the listener.
The above scenario may be desired behavior when the object has a life-cycle
outside the listener, ie., when the object in addition to being registered
with the listener is also kept in a separate list for whatever (different)
purpose. It is certainly not the case all the time though. For instance,
if I create an anonymous object, and simply submit it to the listener, only
the listener has its reference, no one else. This is certainly not what
would ghave been intended, and the above issue will arise.
Of course, the listener can be notified via a reference queue when such an
object is about to be reclaimed, and consequently not allow it to be lost,
presumably via reinsertion into the listener's list. In that case you have
the same problem: "When does the listener get rid of the object?".
In short, I think that weak references can be good for caching type
situations, but in general purpose listeners, this is not the norm, I would
think.
My $0.02
Shripathi Kamath
NETAPHOR SOFTWARE INC.
http://www.netaphor.com
I don't know about most people, but here is what we do:
We identify the life-cyle of the container (the listener), and the
life-cycle of the contained (the object). If the life-cyle of the container
is completely spanned by the life-cycle of the contained, i.e. if the
container is always created after the object, and is always disposed before
the object, we can get away with not caring, i.e. not worrying about
removing the object from the listener. However, if the life-cycle of the
container spans that of the object, i.e., if the container is always created
before the object, and disposed after the object itself has been disposed,
then we make sure that at the time of disposing the object, i.e. removing
all references of the object from the system, we also deregister it from the
listener.
Now this itself can be done in different ways, using procedural code is one
technique. One other technique that we use for such is to create a special
method on the object (i.e. close()) which will contain the deregistraton
procedures. Especially if the object is resident in multiple listeners.
My $0.02 worth, your mileage might vary
HTH,
--
Shripathi Kamath
NETAPHOR SOFTWARE INC.
http://www.netaphor.com
That could have been solved by adding to the register listener method a parameter stating
whether the reference should be hard or weak or even two distinct methods. This
complicates the event dispatching a little bit but greatly simplifies things for all
listeners.
An alternative could be to use an intermediate listener derived from WeakReference that
automatically unregisters itself when its referenced object is GCed.
I haven't tested this but it shows what I mean:
=====================================
import java.lang.ref.WeakReference;
public class EventListenerImpl implements IEventListener
{
public EventListenerImpl() { }
public void handleEvent() { }
public static void main(String[] args) {
// sample registration
EventSource source = new EventSource();
EventListenerImpl listener = new EventListenerImpl();
source.registerListener(new WeakEventListener(listener, source));
}
}
interface IEventListener {
public void handleEvent();
}
class EventSource {
public void registerListener(IEventListener listener){/* ...*/}
public void removeListener(IEventListener listener){/* ...*/}
}
class WeakEventListener extends WeakReference implements IEventListener {
WeakReference source;
public WeakEventListener(IEventListener aListener, EventSource aSource) {
super(aListener);
source = new WeakReference(aSource);
aSource.registerListener(this);
}
public void handleEvent() {
try {
((IEventListener)get()).handleEvent();
}
catch (NullPointerException ex) {
((EventSource)source.get()).removeListener(this);
}
}
}
=====================================
As long as the EventListenerImpl listener object created in main has any hard references
to it it gets the events, but when all references are nulled and it's GCed the
WeakEventListener will automatically unregister it.
Eduardo
De-register in the finalize (or if you have
an earlier place where you know de-registration
is appropriate.)
If you are writing the listener code yourself,
you can use a WeakHashMap to keep the registered
objects (if you know you don't want the registered
objects to stay around after they are otherwise
de-referenced.)
Oops! I wrote that without thinking, it would
be no use of course to do this in the finalize!!