Author: markt Date: Tue Oct 19 15:08:57 2010 New Revision: 1024261 URL: http://svn.apache.org/viewvc?rev=1024261&view=rev Log: Back-port memory leak prevention from Tomcat 7.0.x
Modified: tomcat/tc6.0.x/trunk/STATUS.txt tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java tomcat/tc6.0.x/trunk/webapps/docs/config/listeners.xml Modified: tomcat/tc6.0.x/trunk/STATUS.txt URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/STATUS.txt?rev=1024261&r1=1024260&r2=1024261&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/STATUS.txt (original) +++ tomcat/tc6.0.x/trunk/STATUS.txt Tue Oct 19 15:08:57 2010 @@ -204,11 +204,6 @@ PATCHES PROPOSED TO BACKPORT: timw: fixed in http://svn.apache.org/viewvc?rev=1004912&view=rev * Backport all JRE leak prevention listener changes to tc6 - http://people.apache.org/~markt/patches/2010-10-05-leak-preotection-tc6.patch - +1: markt, kkolinko, kfujino - -1: - - Additional patch: http://svn.apache.org/viewvc?rev=1004868&view=rev http://svn.apache.org/viewvc?rev=1004869&view=rev +1: kkolinko, markt, kfujino Modified: tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?rev=1024261&r1=1024260&r2=1024261&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java (original) +++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java Tue Oct 19 15:08:57 2010 @@ -25,6 +25,7 @@ import java.net.URL; import java.net.URLConnection; import javax.imageio.ImageIO; +import javax.security.auth.Policy; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -49,6 +50,7 @@ import org.apache.tomcat.util.res.String * first disabling Jar URL connection caching. The workaround is to disable this * caching by default. */ +...@suppresswarnings("deprecation") public class JreMemoryLeakPreventionListener implements LifecycleListener { private static final Log log = @@ -66,6 +68,19 @@ public class JreMemoryLeakPreventionList public void setAppContextProtection(boolean appContextProtection) { this.appContextProtection = appContextProtection; } + + /** + * Protect against the memory leak caused when the first call to + * <code>sun.misc.GC.requestLatency(long)</code> is triggered by a web + * application. This first call will start a GC Daemon thread with the + * thread's context class loader configured to be the web application class + * loader. Defaults to <code>true</code>. + */ + private boolean gcDaemonProtection = true; + public boolean isGcDaemonProtection() { return gcDaemonProtection; } + public void setGcDaemonProtection(boolean gcDaemonProtection) { + this.gcDaemonProtection = gcDaemonProtection; + } /** * Protect against the memory leak caused when the first call to @@ -80,6 +95,35 @@ public class JreMemoryLeakPreventionList this.keepAliveProtection = keepAliveProtection; } + /** + * Protect against the memory leak caused when the first call to + * <code>javax.security.auth.Policy</code> is triggered by a web + * application. This first call populate a static variable with a reference + * to the context class loader. Defaults to <code>true</code>. + */ + private boolean securityPolicyProtection = true; + public boolean isSecurityPolicyProtection() { + return securityPolicyProtection; + } + public void setSecurityPolicyProtection(boolean securityPolicyProtection) { + this.securityPolicyProtection = securityPolicyProtection; + } + + /** + * Protect against the memory leak, when the initialization of the + * Java Cryptography Architecture is triggered by initializing + * a MessageDigest during web application deployment. + * This will occasionally start a Token Poller thread with the thread's + * context class loader equal to the web application class loader. + * Instead we initialize JCA early. + * Defaults to <code>true</code>. + */ + private boolean tokenPollerProtection = true; + public boolean isTokenPollerProtection() { return tokenPollerProtection; } + public void setTokenPollerProtection(boolean tokenPollerProtection) { + this.tokenPollerProtection = tokenPollerProtection; + } + /** * Protect against resources being read for JAR files and, as a side-effect, * the JAR file becoming locked. Note this disables caching for all @@ -95,7 +139,9 @@ public class JreMemoryLeakPreventionList /** * XML parsing can pin a web application class loader in memory. This is * particularly nasty as profilers (at least YourKit and Eclipse MAT) don't - * identify any GC roots related to this. + * identify any GC roots related to this. + * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498"> + * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6916498</a> */ private boolean xmlParsingProtection = true; public boolean isXmlParsingProtection() { return xmlParsingProtection; } @@ -103,19 +149,6 @@ public class JreMemoryLeakPreventionList this.xmlParsingProtection = xmlParsingProtection; } - /** - * Protect against the memory leak caused when the first call to - * <code>sun.misc.GC.requestLatency(long)</code> is triggered by a web - * application. This first call will start a GC Daemon thread with the - * thread's context class loader configured to be the web application class - * loader. Defaults to <code>true</code>. - */ - private boolean gcDaemonProtection = true; - public boolean isGcDaemonProtection() { return gcDaemonProtection; } - public void setGcDaemonProtection(boolean gcDaemonProtection) { - this.gcDaemonProtection = gcDaemonProtection; - } - public void lifecycleEvent(LifecycleEvent event) { // Initialise these classes when Tomcat starts if (Lifecycle.INIT_EVENT.equals(event.getType())) { @@ -194,6 +227,31 @@ public class JreMemoryLeakPreventionList } /* + * Calling getPolicy retains a static reference to the context class + * loader. + */ + if (securityPolicyProtection) { + try { + Policy.getPolicy(); + } catch(SecurityException e) { + // Ignore. Don't need call to getPolicy() to be successful, + // just need to trigger static initializer. + } + } + + /* + * Creating a MessageDigest during web application startup + * initializes the Java Cryptography Architecture. Under certain + * conditions this starts a Token poller thread with TCCL equal + * to the web application class loader. + * + * Instead we initialize JCA right now. + */ + if (tokenPollerProtection) { + java.security.Security.getProviders(); + } + + /* * Several components end up opening JarURLConnections without first * disabling caching. This effectively locks the file. Whilst more * noticeable and harder to ignore on Windows, it affects all @@ -237,4 +295,5 @@ public class JreMemoryLeakPreventionList } } } + } Modified: tomcat/tc6.0.x/trunk/webapps/docs/config/listeners.xml URL: http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/webapps/docs/config/listeners.xml?rev=1024261&r1=1024260&r2=1024261&view=diff ============================================================================== --- tomcat/tc6.0.x/trunk/webapps/docs/config/listeners.xml (original) +++ tomcat/tc6.0.x/trunk/webapps/docs/config/listeners.xml Tue Oct 19 15:08:57 2010 @@ -247,7 +247,7 @@ service:jmx:rmi://<hostname>:10002 application do not result in a memory leak. Note that a call to this method will be triggered as part of the web application stop process so it is strongly recommended that this protection is enabled. The default - is <code>true</code></p> + is <code>true</code>.</p> </attribute> <attribute name="gcDaemonProtection" required="false"> @@ -255,7 +255,7 @@ service:jmx:rmi://<hostname>:10002 <code>sun.misc.GC.requestLatency(long)</code> triggered by a web application do not result in a memory leak. Use of RMI is likely to trigger a call to this method. A side effect of enabling this protection - is the creation of a thread named "GC Daemon". The protection is uses + is the creation of a thread named "GC Daemon". The protection uses reflection to access internal Sun classes and may generate errors on startup on non-Sun JVMs. The default is <code>true</code>.</p> </attribute> @@ -270,6 +270,28 @@ service:jmx:rmi://<hostname>:10002 trigger a memory leak on reload. Defaults to <code>true</code>.</p> </attribute> + <attribute name="securityPolicyProtection" required="false"> + <p>Enables protection so that usage of + <code>javax.security.auth.Policy</code> by a web application does not + result in a memory leak. The first access of this class will trigger the + static initializer that will retain a static reference to the context + class loader. The protection calls the <code>getPolicy()</code> method + of this class to ensure that the static initializer is not triggered by + a web application. Defaults to <code>true</code>.</p> + </attribute> + + <attribute name="tokenPollerProtection" required="false"> + <p>Enables protection so that any token poller thread initialized by + <code>sun.security.pkcs11.SunPKCS11.initToken()</code> does not + result in a memory leak. The thread is started depending on various + conditions as part of the initialization of the Java Cryptography + Architecture. Without the protection this can happen during Webapp + deployment when the MessageDigest for generating session IDs is + initialized. As a result the thread has the Webapp class loader as its + thread context class loader. Enabling the protection initializes JCA + early during Tomcat startup. Defaults to <code>true</code>.</p> + </attribute> + <attribute name="urlCacheProtection" required="false"> <p>Enables protection so that reading resources from JAR files using <code>java.net.URLConnection</code>s does not result in the JAR file --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org