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>--> > ../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>--> ../object/0xeb7b52d0 java.util.hash...@0xeb7b52d0 (40 bytes) > > (field table:)<br> > --> ../object/0xeb7b52f8 [Ljava.util.HashMap$Entry;@0xeb7b52f8 (40 > bytes) > (Element 0 of [Ljava.util.HashMap$Entry;@0xeb7b52f8:)<br> > --> ../object/0xeb7b5388 java.util.hashmap$en...@0xeb7b5388 (24 bytes) > (field key:)<br> > --> ../object/0xeb7b53a0 > sun.rmi.server.loaderhandler$loader...@0xeb7b53a0 (20 bytes) > (field parent:)<br> > --> ../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>--> ../object/0xeb400668 > org.apache.catalina.core.standardser...@0xeb400668 (67 bytes) > (field services:)<br> > --> ../object/0xeb4b4178 [Lorg.apache.catalina.Service;@0xeb4b4178 (12 > bytes) > (Element 0 of [Lorg.apache.catalina.Service;@0xeb4b4178:)<br> > --> ../object/0xeb4b4188 > org.apache.catalina.core.standardserv...@0xeb4b4188 (62 bytes) > (field container:)<br> > --> ../object/0xeb4b42c8 > org.apache.catalina.core.standardeng...@0xeb4b42c8 (129 bytes) > (field thread:)<br> > --> ../object/0xeb58b6e0 java.lang.thr...@0xeb58b6e0 (104 bytes) > (field threadLocals:)<br> > --> ../object/0xeb58b800 java.lang.threadlocal$threadlocal...@0xeb58b800 > (20 bytes) > (field table:)<br> > --> ../object/0xeb58b818 > [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;@0xeb58b818 (72 bytes) > (Element 8 of > [Ljava.lang.ThreadLocal$ThreadLocalMap$Entry;@0xeb58b818:)<br> > --> ../object/0xeb58b908 > java.lang.threadlocal$threadlocalmap$en...@0xeb58b908 (28 bytes) > (field value:)<br> > > --> ../object/0xeb58b928 java.util.hash...@0xeb58b928 (40 bytes) > (field table:)<br> > --> ../object/0xeb58b950 [Ljava.util.HashMap$Entry;@0xeb58b950 (72 > bytes) > (Element 0 of [Ljava.util.HashMap$Entry;@0xeb58b950:)<br> > --> ../object/0xeb58bb40 java.util.hashmap$en...@0xeb58bb40 (24 bytes) > > (field key:)<br> > --> ../object/0xdbe798a0 class org.apache.axis.types.Notation (84 bytes) > (??:)<br> > --> ../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