Home > Java, Programming > Java Observer/Observable caveat

Java Observer/Observable caveat

April 23rd, 2010 jmguilla

This post is also available in: French

ProActive Virtual Machine Management is a project in which I am invested. In several places we needed to use the Java Observer/Observable pattern but weren’t really satisfied by the way Observers are saved, this way can leads to important memory leaks in APIs where the end user doesn’t not explicitly release objects. Indeed, all listeners are not garbagge collected just because they are in the listener list.

To avoid memory leaks, we wrote our own Observer/Obserable feature based on WeakReference. Here is the code:

NotifierAdapter class is the equivalent of Observable

public class NotifierAdapter implements Notifier {
    private ArrayList<WeakReference<NotifierListener<N, T>>> listeners = new ArrayList<WeakReference<NotifierListener<N, T>>>();
    private N notifier;
 
    protected NotifierAdapter() {
        this.notifier = (N) this;
    }
 
    public NotifierAdapter(N notifier) {
        this.notifier = notifier;
    }
 
    public void addNotifierListener(NotifierListener<N, T> listener) {
        WeakReference<NotifierListener<N, T>> weakListenerReference = new WeakReference<NotifierListener<N, T>>(listener);
        this.listeners.add(weakListenerReference);
    }
 
    public void removeNotifierListener(NotifierListener<N, T> listener) {
        for (int i = 0; i < this.listeners.size(); i++) {
            WeakReference<NotifierListener<N, T>> weakListenerReference = this.listeners.get(i);
            NotifierListener<N, T> weakListener = weakListenerReference.get();
            if ((weakListener == null) || (weakListener == listener)) {
                this.listeners.remove(weakListenerReference);
            }
        }
    }
 
    public void fire(T event) {
        ArrayList<WeakReference<NotifierListener<N, T>>> toDelete = new ArrayList<WeakReference<NotifierListener<N, T>>>();
        for (WeakReference<NotifierListener<N, T>> weakListenerReference : listeners) {
            NotifierListener<N, T> weakListener = weakListenerReference.get();
            if (weakListener == null) {
                toDelete.add(weakListenerReference);
            } else {
                weakListener.update(this.notifier, event);
            }
        }
        listeners.removeAll(toDelete);
    }
}

The equivalent of the Observer interface: NotifierListener

public interface NotifierListener {
    public void update(N notifier, T event);
}

And the Notifier interface

public interface Notifier {
    public void addNotifierListener(NotifierListener listener);
 
    public void removeNotifierListener(NotifierListener listener);
 
    public void fire(T event);
}
Categories: Java, Programming Tags: ,
Comments are closed.