Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49230
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Tue, 22 Jun 2010 09:21:25 +0000 (09:21 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Tue, 22 Jun 2010 09:21:25 +0000 (09:21 +0000)
Enhance JRE leak prevention listener with protection for the keep-alive thread started by sun.net.www.http.HttpClient
Patch provided by Rob Kooper.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@956832 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
webapps/docs/changelog.xml
webapps/docs/config/listeners.xml

index 800a9eb..b243d83 100644 (file)
@@ -80,6 +80,19 @@ public class JreMemoryLeakPreventionListener implements LifecycleListener {
         this.gcDaemonProtection = gcDaemonProtection;
     }
 
+     /**
+      * Protect against the memory leak caused when the first call to
+      * <code>sun.net.www.http.HttpClient</code> is triggered by a web
+      * application. This first call will start a KeepAlive thread with the
+      * thread's context class loader configured to be the web application class
+      * loader. Defaults to <code>true</code>.
+      */
+     private boolean keepAliveProtection = true;
+     public boolean isKeepAliveProtection() { return keepAliveProtection; }
+     public void setKeepAliveProtection(boolean keepAliveProtection) {
+         this.keepAliveProtection = keepAliveProtection;
+     }
+    
     /**
      * Protect against the memory leak, when the initialization of the
      * Java Cryptography Architecture is triggered by initializing
@@ -177,6 +190,21 @@ public class JreMemoryLeakPreventionListener implements LifecycleListener {
                     log.error(sm.getString("jreLeakListener.gcDaemonFail"), e);
                 }
             }
+
+            /*
+             * When a servlet opens a connection using a URL it will use
+             * sun.net.www.http.HttpClient which keeps a static reference to a
+             * keep-alive cache which is loaded using the web application class
+             * loader.
+             */
+            if (keepAliveProtection) {
+                try {
+                    Class.forName("sun.net.www.http.HttpClient");
+                } catch (ClassNotFoundException e) {
+                    log.error("Could not prevent sun.net.www.http.HttpClient" +
+                               " from being loaded.", e);
+                }
+            }
             
             /*
              * Creating a MessageDigest during web application startup
index 0a12880..8cc2600 100644 (file)
       <add>
         Add entryPoint support to the CSRF prevention filter. (markt)
       </add>
+      <fix>
+        <bug>49230</bug>: Enhance JRE leak prevention listener with protection
+        for the keep-alive thread started by
+        <code>sun.net.www.http.HttpClient</code>. Patch provided by Rob Kooper.
+        (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Jasper">
index 9f3d023..c15c03f 100644 (file)
@@ -260,6 +260,16 @@ service:jmx:rmi://&lt;hostname&gt;:10002/jndi/rmi://&lt;hostname&gt;:10001/jmxrm
         startup on non-Sun JVMs. The default is <code>true</code>.</p>
       </attribute>
 
+      <attribute name="keepAliveProtection" required="false">
+        <p>Enables protection so that the KeepAlive thread started by
+        <code>sun.net.www.http.HttpClient</code> does not result in a memory
+        leak. The thread is started the first time the <code>HttpClient</code>
+        class is used. Without this protection, if a web application uses this
+        class the KeepAlive thread will be configured with the thread's context
+        class loader set to the web application class loader which in turn will
+        trigger a memory leak on reload. 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