hivemind-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jean-Francois Poilpret" <>
Subject RE: Erratum: Potential memory leak with Threaded model and Events listeners
Date Sun, 05 Dec 2004 00:36:31 GMT

In my previous mail, replace both appearances of XXXX with
activateService/deactivateService respectively. I pushed the "send" button
too eagerly;-)

-----Original Message-----
From: Jean-Francois Poilpret [] 
Sent: Sunday, December 05, 2004 7:34 AM
Subject: RE: Potential memory leak with Threaded model and Events listeners

No, I don't want each __created__ instance to receive notifications, I just
want each __active__ instance to receive them, and any __inactive___
instance not to receive them.
Currently with either threaded or pooled model (as far as I can see), all
created instances actually receive notifications, even when inactive. Worse,
for threaded model, inactive instances never get garbage-collected because
they are strongly referenced by the service which fire events.

For me, the expected behavior of HiveMind would be:
- when a service instance gets created (threaded) or activated (pooled),
then it should be added as a listener to the service firing events
- when a service instance gets discarded (threaded) or deactivated (pooled),
then it should be removed as a listener from the service supplying events.

NB: this description applies to the case where the event-firing service is a
singleton (my situation right now), but the behavior would/should probably
be different if that service used a different model.

Currently, the best work-around is:
- for threaded model, the listening service must implement Discardable and
remove itself from the listeners list of the event firing service, when its
threadDidDiscardService() method is called. The registration as a listener
can either be done by configuration (BuilderFactory) or in the constructor.

- for pooled model, the listening service must implement PoolManageable and
it must register itself as a listener in its XXXX methods, and unregister
itself when its XXXX() method is called. Here automatic Event registration
through BuilderFactory is useless.

These work-arounds work well, but they are not very "clean" in the sense
that this is code the end-developer has to write that HiveMind could
directly handle for him.
In addition, in the threaded situation, if we use the BuilderFactory to wire
the listener to the event supplier, then the work-around introduces some
asymmetry (registration in config, unregistration in the code), making the
use of BuilderFactory for this aspect useless.

I think before changing anything in HiveMind, we (all concerned developers)
should discuss the various situations (models for supplier/consumer:
singleton/threaded, singleton/pooled, threaded/singleton,
threaded/threaded...) and specify for each what the behavior should be, then
the actual coding can start. Should we start a new page on the WIKI?


-----Original Message-----
From: Howard Lewis Ship [] 
Sent: Sunday, December 05, 2004 4:09 AM
Subject: Re: Potential memory leak with Threaded model and Events listeners

If you want each created instance to receive the notification, use the
pooled, not threaded, service model.  Pooled instances exist
indefinately once created.  The only down side is that code related to
the event needs to be thread safe, and that deactivated instances in
the pool will also receive notifications.

On Sun, 5 Dec 2004 00:18:27 +0700, Jean-Francois Poilpret
<> wrote:
> Hi Luke,
> Thank you for your remark.
> Although your remark is correct in many cases of Listeners, I think it
> generally not apply in HiveMind context, I mean (if people follow the
> path") that normally, only a service will implement a Listener interface,
> thus at least HiveMind itself (through one of the generated proxies) will
> hold a strong reference to that service/listener. But of course, if
> decides to create a Listener on-the-fly and add it "by hand" to the event
> supplier service, then the problem you described would occur.
> Anyway, I just did some tests (with strong and with weak references) and
> fact, the result is not "as good" as I expected initially. Indeed, when
> suggesting that idea, I simply forgot that the handling of weak references
> is totally non-deterministic, ie the weak ref could still be valid even
> though there is no more existing strong ref. The time at which the weak
> would be cleaned is totally up to the GC...
> So as my test have shown me, using weak refs improve the issue, but they
> not solve it really:-(
> In my tests, I did something like that:
> - create EventSupplier service (singleton)
> - create EventConsumer service (threaded)
> - instantiate EventConsumer in 1000 "threads" (they are real threads but
> they do not run concurrently, but I force consecutive runs, with a call to
> Registry.cleanupThread() at the end of each thread)
> - each thread call the EventSupplier to generate a new event
> - all calls are traced
> - each EventConsumer instance allocates 10KB on the heap and never release
> them.
> With strong refs:
> - the 1000th thread sends an event that is received by 1000 EventConsumer
> instances
> With weak refs:
> - the 1000th thread sends an event that is received by about 30
> EventConsumer instances.
> Of course that is much better, but the ideal, here in my testcase, would
> always just one EventConsumer instance receiving the event.
> So finally, maybe I will stick with the previous -not very clean from
> viewpoint- workaround:
> - have EventConsumer implement Discardable and remove itself from the
> EventSupplier list of listeners, when threadDidDiscardService() is called.
> And then I will eagerly wait for HM1.1 release (hope it will fix this
> issue).
> Cheers
> -----Original Message-----
> From: Luke Blanshard []
> Sent: Saturday, December 04, 2004 8:13 PM
> To:
> Subject: Re: Potential memory leak with Threaded model and Events
> Jean-Francois,
> The problem with holding listeners weakly is that people commonly create
> listener objects on the fly and then retain no other references to them
> once they've added them.  So these listeners are thrown away on the next
> GC cycle, and they stop working.
> One solution to this is to have a tagging interface (we call ours
> WeakListener) that tells the event source that it should hold the
> listener weakly.  All listeners that don't implement this interface are
> held strongly.  This way, you as the implementer of the listener are
> telling the event source whether to hold the listener weakly (meaning
> you better have a strong reference to it) or strongly (meaning you don't
> have to).  As you say, it's pretty easy to write a listeners collection
> that honors this WeakListener interface and throws away the expired
> listeners when you ask for the current list of listeners.  (We don't use
> an iterator, but rather a method that returns an array of listeners, for
> thread safety reasons.)
> Luke
> Jean-Francois Poilpret wrote:
> >...
> >To Howard:
> >During the night (French people say that the "night gives good
> >I thought of a quite easy workaround, that can be done at the event
> >supplying service level: just use a weak reference to the listeners
> (instead
> >of a strong one), I think that should do the trick.
> >Maybe it would even be possible to write a general "WeakEventListeners"
> >class to manage all that for the event supplier:
> >- when addListener, is called generate a weak reference to the added
> >listener and store it in the list
> >- create a specific Iterator for WeakEventListeners that would skip the
> refs
> >that have become weak-reachable (and remove these from its list at the
> >time).
> >
> >
> ---------------------------------------------------------------------
> To unsubscribe, e-mail:
> For additional commands, e-mail:
> ---------------------------------------------------------------------
> To unsubscribe, e-mail:
> For additional commands, e-mail:

Howard M. Lewis Ship
Independent J2EE / Open-Source Java Consultant
Creator, Jakarta Tapestry
Creator, Jakarta HiveMind

To unsubscribe, e-mail:
For additional commands, e-mail:

To unsubscribe, e-mail:
For additional commands, e-mail:

To unsubscribe, e-mail:
For additional commands, e-mail:

View raw message