tomcat-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Endre StĂžlsvik <En...@Stolsvik.com>
Subject Re: Memory leaking on [un|re]load: WebappClassLoader isn't GC'ed
Date Thu, 26 Jan 2006 11:07:07 GMT
On Thu, 26 Jan 2006, Davide Romanini wrote:

| Il giorno mer, 25/01/2006 alle 11.12 -0800, Wade Chandler ha scritto:
| 
| > Don't use shared libraries and you shouldn't have this
| > problem.  If all of the statics are in your WEB-INF
| > directory then you won't have an issue with unloading
| > classes and class loaders.
| > 
| 
| It would be great if could be so simple. But it is not, trust me, my
| shared folder is empty, and the common/lib folder contains only jdbc
| drivers and javamail implementation (needed by Tomcat if you want to use
| JNDI mail sessions). All the libraries of the webapp are in WEB-INF/lib
| folder. As I said in previous mail, I tried to reload the distribution
| version of Axis (just as is, without other libs) and it causes the
| problem. It seems that something occuring during AxisServlet startup (it
| looks for his configuration using a complex discovery process) causes
| some class of a parent classloader to hold a reference to
| WebappClassloader so it cannot be GC'ed when it's reloaded.

But, try to reload the tomcat-docs webapp. That happens without problems. 
And as I mentioned, if I comment out pretty much the entire "startup" of 
my webapp, it can be reloaded just fine.
  In particular, I definately can't start WebMacro (which (tries to) read 
files through both the classloader and File and URL), nor read the 
Configuration (which uses JDOM, which uses SAX) and still have 
reload-functionality. This _really_ bugs me!

| 
| Surely it's not a Tomcat problem anyway...

That I really hope, but as of now I can't rule it out. I've tried with 
several Tomcat versions (4, 5, 5.5), all with the same result. But I'll 
give Jetty a try too..!

However, all the objects that are lingering have some root going through 
some mbean-server and whatnot, and ends up in static fields of tomcat. 
Unless these instances also are held by "my" WebappClassLoader (which due 
to the names of the classes I tend to not believe; they seem so "rooty"), 
there is _something_ that in certain situations keeps some reference to 
some object of the webapp. But I'm not at the bottom of those objects yet.

Remember that only _one single reference_ to _any_ object of the webapp 
will hold pretty much the _entire_ webapp from unloading: This is because 
each object holds a ref to its class, which again holds a ref to its 
classloader, which again holds refs to all classes loaded in the 
classloader, which again have static fields, which again probably holds a 
whole bunch of your actual objects.

ThreadLocals as they are implemented in Java 1.4 and still, are apparently 
very dangerous for Servlet Containers, Tomcat included.

ThreadLocals are implemented as follows: The Thread object contains a 
hashmap whose Entries have weak key and hard value. The key is the 
ThreadLocal instance, and the value is the actual referent (the object 
returned by threadLocal.get()). The ThreadLocal instance confers this map 
for finding its value for the current Thread. This can be done 
unsyncronized, since it's obviously singlethreaded (its a map within the 
Thread!).
  Thus, when a ThreadLocal instance goes out of scope, its key will be 
GCable, which due to the coding of ThreadLocal at some point later, 
hopefully, will release the value (it "scavenges" dead keys on subsequent 
sets (of any other TL instance)).

Now, ThreadLocals instances are often declarder as a "static (final)", 
right?

In situations where the ClassLoader is ditched, while the Threads are 
recycled, this _instantly_ creates an enourmous leak: The ThreadLocalMap 
instance within the Thread contains an Entry with a weak reference to the 
ThreadLocal static instance, and a hard reference to the value. The value 
has a hard reference to its ClassLoader. The ClassLoader have a hard 
reference to the Class that contains the ThreadLocal static instance - 
hence the key is still hard reachable, and thus the key won't be nulled 
and GC'ed - and thus again the Thread.ThreadLocalMap.Entry instance won't 
ever be scavenged, and the Thread will forever after contain a hard 
reference to the now-not-used ClassLoader. (- which as explained above 
holds all the WebApp's classes, which have static fields, which point to 
structures within your web application, and you're screwed).

Check out "Tackline"'s blog entry, which is the source of this information 
(I've hopefully understood his analysis!)
  http://www.jroller.com/page/tackline?entry=fixing_threadlocal

This fine page also mentions ThreadLocals vs. Tomcat, but fails to point 
out that this should be viewed as a flaw with ThreadLocals:
  http://opensource2.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669

If you agree to this analysis, then vote for this bug:
  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6254531

;-)

Regards,
Endre.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Mime
View raw message