Skip to content

Commit a58313b

Browse files
committed
Make sure that event handlers are not GC'ed prematurely
Unfortunately, our ProxySubscriber instances were garbage collected rather quickly because there was no reference to them (references to the event handler object do not prevent ProxySubscribers from being GCed). So let's make sure that there are references to each ProxySubscriber as long as there are still references to the corresponding event handler object. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 4dd8a80 commit a58313b

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

src/main/java/org/scijava/event/DefaultEventService.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import java.util.ArrayList;
4141
import java.util.Collection;
4242
import java.util.List;
43+
import java.util.WeakHashMap;
4344

4445
import org.bushe.swing.event.annotation.AbstractProxySubscriber;
4546
import org.bushe.swing.event.annotation.BaseProxySubscriber;
@@ -209,6 +210,37 @@ private Class<? extends SciJavaEvent> getEventClass(final Method m) {
209210
return eventClass;
210211
}
211212

213+
// -- Event handlers garbage collection preventer --
214+
215+
private WeakHashMap<Object, List<ProxySubscriber<?>>> keepEm =
216+
new WeakHashMap<Object, List<ProxySubscriber<?>>>();
217+
218+
/**
219+
* Prevents {@link ProxySubscriber} instances from being garbage collected
220+
* prematurely.
221+
* <p>
222+
* We instantiate a {@link ProxySubscriber} for each method with an
223+
* {@link EventHandler} annotation. These instances are then passed to the
224+
* EventBus. The way the instances are created ensures that the event handlers
225+
* will be held only as weak references. But they are weak references to the
226+
* {@link ProxySubscriber} instances rather than the object containing the
227+
* {@link EventHandler}-annotated methods. Therefore, we have to make sure
228+
* that there is a non-GC'able reference to each {@link ProxySubscriber} as
229+
* long as there is a reference to the containing event handler object.
230+
* </p>
231+
*
232+
* @param o the object containing {@link EventHandler}-annotated methods
233+
* @param subscriber a {@link ProxySubscriber} for a particular {@link EventHandler}
234+
*/
235+
private synchronized void keepIt(final Object o, final ProxySubscriber<?> subscriber) {
236+
List<ProxySubscriber<?>> list = keepEm.get(o);
237+
if (list == null) {
238+
list = new ArrayList<ProxySubscriber<?>>();
239+
keepEm.put(o, list);
240+
}
241+
list.add(subscriber);
242+
}
243+
212244
// -- Helper classes --
213245

214246
/**
@@ -229,6 +261,7 @@ private class ProxySubscriber<E extends SciJavaEvent> extends
229261

230262
public ProxySubscriber(final Class<E> c, final Object o, final Method m) {
231263
super(o, m, ReferenceStrength.WEAK, eventBus, false);
264+
keepIt(o, this);
232265
this.c = c;
233266

234267
// allow calling of non-public methods

0 commit comments

Comments
 (0)