On 26/07/2010 09:16, Arjen Knibbe wrote:
> 
> After being plaged by PermGen space OutOfMemoryErrors I came across an 
> http://java.dzone.com/articles/memory-leak-protection-tomcat interview with
> Mark Thomas  announcing the solution for these kinds of memory leaks. I
> upgraded Tomcat 6.0.26 on Solaris 5.8 machine and repeatedly deployed and
> undeployed my applications. However, the problem remained. After many weeks,
> I think I got it:

Many, many thanks for your efforts and for writing this up. This looks
great.

Please could you create a Bugzilla entry (against Tomact 7) for each
issue you identified so that this valuable work doesn't get forgotten about?

95% of the work should just be a copy and paste.

Again, many thanks.

Mark

PS How do you fancy trying to fix some of these issues?


> Besides the enhanced WebappClassLoader the new Tomcat uses a Listener
> org.apache.catalina.core.JreMemoryLeakPreventionListener, that has to be
> included in the server.xml file. By upgrading, I missed that.
> 
> The class javax.security.auth.Policy has a static member contextClassLoader
> that can refer to the WebappClassLoader.
> from jhat:
> <h3>Static reference from
> javax.security.auth.Policy.contextClassLoader<small> (from 
> ../object/0xdc035580 class javax.security.auth.Policy) </small> :</h3>--&gt; 
> ../object/0xeb5a84a0 org.apache.catalina.loader.webappclassloa...@0xeb5a84a0
> (157 bytes) 
> <br>
> 
> The class sun.rmi.server.LoaderHander has a static member LoaderTable that
> can contain the WebappClassLoader when using RMI.
> From jhat:
> <h3>Static reference from sun.rmi.server.LoaderHandler.loaderTable<small>
> (from  ../object/0xdbf2b258 class sun.rmi.server.LoaderHandler) </small>
> :</h3>--&gt;  ../object/0xeb7b52d0 java.util.hash...@0xeb7b52d0 (40 bytes) 
> 
>  (field table:)<br>
> --&gt;  ../object/0xeb7b52f8 [Ljava.util.HashMap$Entry;@0xeb7b52f8 (40
> bytes) 
>  (Element 0 of [Ljava.util.HashMap$Entry;@0xeb7b52f8:)<br>
> --&gt;  ../object/0xeb7b5388 java.util.hashmap$en...@0xeb7b5388 (24 bytes) 
>  (field key:)<br>
> --&gt;  ../object/0xeb7b53a0
> sun.rmi.server.loaderhandler$loader...@0xeb7b53a0 (20 bytes) 
>  (field parent:)<br>
> --&gt;  ../object/0xeb5a84a0
> org.apache.catalina.loader.webappclassloa...@0xeb5a84a0 (157 bytes) 
> <br>
> 
> The clearReferencesThreadLocals() method of WebappClassLoader clears two
> Thread tables from references to the WebappClassLoader. When using axis, the
> tables can have a HashMap as key, which contains (possibly after many nested
> HashMaps) a class that was loaded by the WebappClassLoader.
> From jhat:
> <h3>Static reference from org.apache.catalina.ServerFactory.server<small>
> (from  ../object/0xdba00178 class org.apache.catalina.ServerFactory)
> </small> :</h3>--&gt;  ../object/0xeb400668
> org.apache.catalina.core.standardser...@0xeb400668 (67 bytes) 
>  (field services:)<br>
> --&gt;  ../object/0xeb4b4178 [Lorg.apache.catalina.Service;@0xeb4b4178 (12
> bytes) 
>  (Element 0 of [Lorg.apache.catalina.Service;@0xeb4b4178:)<br>
> --&gt;  ../object/0xeb4b4188
> org.apache.catalina.core.standardserv...@0xeb4b4188 (62 bytes) 
>  (field container:)<br>
> --&gt;  ../object/0xeb4b42c8
> org.apache.catalina.core.standardeng...@0xeb4b42c8 (129 bytes) 
>  (field thread:)<br>
> --&gt;  ../object/0xeb58b6e0 java.lang.thr...@0xeb58b6e0 (104 bytes) 
>  (field threadLocals:)<br>
> --&gt;  ../object/0xeb58b800 java.lang.threadlocal$threadlocal...@0xeb58b800
> (20 bytes) 
>  (field table:)<br>
> --&gt;  ../object/0xeb58b818
> [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;@0xeb58b818 (72 bytes) 
>  (Element 8 of
> [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;@0xeb58b818:)<br>
> --&gt;  ../object/0xeb58b908
> java.lang.threadlocal$threadlocalmap$en...@0xeb58b908 (28 bytes) 
>  (field value:)<br>
> 
> --&gt;  ../object/0xeb58b928 java.util.hash...@0xeb58b928 (40 bytes) 
>  (field table:)<br>
> --&gt;  ../object/0xeb58b950 [Ljava.util.HashMap$Entry;@0xeb58b950 (72
> bytes) 
>  (Element 0 of [Ljava.util.HashMap$Entry;@0xeb58b950:)<br>
> --&gt;  ../object/0xeb58bb40 java.util.hashmap$en...@0xeb58bb40 (24 bytes) 
> 
>  (field key:)<br>
> --&gt;  ../object/0xdbe798a0 class org.apache.axis.types.Notation (84 bytes) 
>  (??:)<br>
> --&gt;  ../object/0xeb5a84a0
> org.apache.catalina.loader.webappclassloa...@0xeb5a84a0 (157 bytes) 
> <br>
> 
> Suppose there is an web application A that uses a database and registers a
> Driver with the java.sql.DriverManager, and a web application B that doesn't
> use a database but has a jar file in its WEB-INF/lib directory that contains
> the same Driver. Suppose you unload webapplication B.
> Running the org.apache.catalina.loader.JdbcLeakPrevention class will
> actually register the Driver and leave it loaded! The cause is the way the
> DriverManager checks whether a ClassLoader has permission to load the
> Driver. It does that by calling ClassForName with the ClassLoader, which
> will load the class if the class has not been loaded by that ClassLoader.
> And loading a Driver triggers the Driver to register itself.
> Seems that the loop in org.apache.catalina.loader.JdbcLeakPrevention has to
> be run twice.
> 
> I included the org.apache.catalina.core.JreMemoryLeakPreventionListener in
> my server.xml file.
> In the destroy method of my servlet, I did the following:
> <ul>
> <li>Set javax.security.auth.Policy.contextClassLoader to null if it
> referenced the WebappClassLoader.</li>
> <li>Iterates over the sun.rmi.server.LoaderHandler$LoaderKey items in
> sun.rmi.server.LoaderHandler, removing items whose parent field referred to
> the WebappClassLoader.</li>
> <li>Traverse Collections and Maps in the two java.lang.ThreadLocal table
> fields, clearing all deep references to the WebappClassLoader.</li>
> </ul>
> After that, my classes were unloaded after undeploy.
> 
> Arjen




---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to