Thread leak with ReloadingCacheManager
Alex Twisleton-Wykeham-Fiennes <[email protected]> Wed, 8 Mar 2006 10:39:23 +0000
| Newsgroups | gmane.comp.java.webmacro.user |
|---|---|
| Message-ID | <[email protected]> |
All,
I've just been spending a couple of days trying to track down why memory gets
consumed when reloading the same web application under tomcat which according
to my research is related to class loader confusion [1].
During the course of my testing (running OptimizeIt across the tomcat5 process
and analysing class loading and object creation across multiple reloads),
I've been noticing the number of Threads growing with each reload which
didn't seem correct at all.
The increasing threads were getting allocated by ReloadingCacheManager and
where being utilised by the ClockDaemon process for triggering the expiration
of assets from the template and url Providers (using the standard webmacro
defaults file).
These would normally get destroyed when the destroy() method was invoked on
the ReloadingCacheManager, but I couldn't find any where that enabled me to
do this easily. I would have expected this to be invoked in the destroy()
method of WMServlet but this is not the case:-
public synchronized void destroy ()
{
stop();
_log.notice("stopped: " + this);
_wm = null;
_started = false;
super.destroy();
}
In the end, I found it very hard to find a way to cleanly persuade the
webmacro instance to shut itself down properly, and ended up putting
something like this in my stop() method for my subclass of WMServlet:-
protected void stop()
{
// tidy up my stuff... <snip>
Broker broker = getBroker();
try {
Provider templateProvider = broker.getProvider("template");
templateProvider.destroy();
Provider urlProvider = broker.getProvider("url");
urlProvider.destroy();
} catch (NotFoundException nfEx) {
nfEx.printStackTrace();
}
super.stop();
}
Now this nicely tidies up the appropriate resources and when I reload this
application lots of times the thread count stays consistent, my memory is
much more under control and everything is a bit smoother.
So, my question is:-
Assuming that ReloadingCacheManager has to be destroy()ed correctly to get it
to shut down, and assuming that the application author doesn't know which
Providers are going to be implemented using a ReloadingCacheManager (as it is
defined by the properties classes at runtime), then what would be the
"correct" way of ensuring that the framework is correctly shut down?
Previously there was a definition of WebMacro.destroy() that stated "Call this
method when you are finished with WebMacro. If you don't call this method,
the Broker and all of WebMacro's caches may not be properly shut down,
potentially resulting in loss of data, and wasted memory. This method is
called in the finalizer, but it is best to call it as soon as you know you
are done with WebMacro.", but this has since been dropped from the package.
My gut feeling is that there should be a destroy() method on the Broker that
then invokes destroy() on all of the sub-components that it is maintaining
references to, but I am not that familiar with the webmacro hierarchy...
All tests have been run against 2.0b1, but the changelog to 2.0RC1 doesn't
touch upon any of these changes as far as I can see.
Alex
[1]
http://opensource2.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642