diff -r 8b1346a61d5d javafx-ui-controls/src/com/sun/javafx/scene/control/WeakEventHandler.java --- a/javafx-ui-controls/src/com/sun/javafx/scene/control/WeakEventHandler.java Tue Oct 11 17:02:02 2011 -0700 +++ b/javafx-ui-controls/src/com/sun/javafx/scene/control/WeakEventHandler.java Tue Oct 11 17:02:06 2011 -0700 @@ -24,12 +24,15 @@ */ package com.sun.javafx.scene.control; +import java.lang.ref.ReferenceQueue; import javafx.event.Event; import javafx.event.EventHandler; import javafx.event.EventTarget; import javafx.event.EventType; import java.lang.ref.WeakReference; import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; /** * A Weak reference EventHandler wrapper in the same way as javafx.beans.value.WeakChangeListener works. @@ -37,11 +40,25 @@ * This assumes the EventTarget has a standard "removeEventHandler" method. */ public class WeakEventHandler implements EventHandler { + + private static ReferenceQueue referenceQueue = new ReferenceQueue(); + private static Map weakReferencesMap = new HashMap(); - private final WeakReference> ref; - private final EventTarget target; - private final EventType type; + private final WeakReference> ref; + private final EventProperties eventProperties; + private static class EventProperties { + private final EventTarget target; + private final EventType type; + private final WeakEventHandler eventHandler; + + public EventProperties(EventTarget target, EventType type, WeakEventHandler eventHandler) { + this.target = target; + this.type = type; + this.eventHandler = eventHandler; + } + } + /** * The constructor of {@code WeakEventHandler}. * @@ -51,9 +68,12 @@ if (listener == null) { throw new NullPointerException("Listener must be specified."); } - this.target = target; - this.type = type; - this.ref = new WeakReference>(listener); + this.eventProperties = new EventProperties(target, type, this); + this.ref = new WeakReference>(listener, referenceQueue); + weakReferencesMap.put(ref, eventProperties); + + // clean up the reference queue for any dead references + cleanupReferenceQueue(); } @Override public void handle(T t) { @@ -61,15 +81,28 @@ if (eventHandler != null) { eventHandler.handle(t); } else { - // The weakly reference listener has been garbage collected, - // so this WeakListener will now unhook itself from the - // source bean - try { - Method removeEventHandler = target.getClass().getMethod("removeEventHandler", EventType.class, EventHandler.class); - removeEventHandler.invoke(target,type, this); - } catch (Exception e) { - e.printStackTrace(); - } + cleanup(ref, eventProperties); + } + } + + private static void cleanup(WeakReference ref, EventProperties eventProperties) { + // The weakly reference listener has been garbage collected, + // so this WeakListener will now unhook itself from the + // source bean + try { + Method removeEventHandler = eventProperties.target.getClass().getMethod("removeEventHandler", EventType.class, EventHandler.class); + removeEventHandler.invoke(eventProperties.target,eventProperties.type, eventProperties.eventHandler); + EventProperties ep = weakReferencesMap.remove(ref); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void cleanupReferenceQueue() { + WeakReference ref = null; + while ((ref = (WeakReference) referenceQueue.poll()) != null) { + EventProperties eventProperties = weakReferencesMap.get(ref); + cleanup(ref, eventProperties); } } }