You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2017/01/09 21:50:53 UTC

svn commit: r1778061 - in /tomcat/trunk: build.xml java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java webapps/docs/changelog.xml webapps/docs/config/listeners.xml

Author: markt
Date: Mon Jan  9 21:50:53 2017
New Revision: 1778061

URL: http://svn.apache.org/viewvc?rev=1778061&view=rev
Log:
Add memory protection for ForkJoinPool.commonPool() related memory leaks.

Added:
    tomcat/trunk/java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java   (with props)
Modified:
    tomcat/trunk/build.xml
    tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/listeners.xml

Modified: tomcat/trunk/build.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/build.xml?rev=1778061&r1=1778060&r2=1778061&view=diff
==============================================================================
--- tomcat/trunk/build.xml (original)
+++ tomcat/trunk/build.xml Mon Jan  9 21:50:53 2017
@@ -336,6 +336,8 @@
     <include name="org/apache/catalina/startup/CatalinaProperties.*" />
     <include name="org/apache/catalina/startup/ClassLoaderFactory.*" />
     <include name="org/apache/catalina/startup/ClassLoaderFactory$*.*" />
+    <include name="org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.*" />
+    <include name="org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory$*.*" />
     <include name="org/apache/catalina/startup/Tool.*" />
     <include name="org/apache/catalina/security/SecurityClassLoad.*" />
     <include name="org/apache/catalina/webresources/war/**" />

Modified: tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java?rev=1778061&r1=1778060&r2=1778061&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java (original)
+++ tomcat/trunk/java/org/apache/catalina/core/JreMemoryLeakPreventionListener.java Mon Jan  9 21:50:53 2017
@@ -25,6 +25,7 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.sql.DriverManager;
 import java.util.StringTokenizer;
+import java.util.concurrent.ForkJoinPool;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
@@ -33,6 +34,7 @@ import javax.xml.parsers.ParserConfigura
 import org.apache.catalina.Lifecycle;
 import org.apache.catalina.LifecycleEvent;
 import org.apache.catalina.LifecycleListener;
+import org.apache.catalina.startup.SafeForkJoinWorkerThreadFactory;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
 import org.apache.tomcat.util.ExceptionUtils;
@@ -63,6 +65,8 @@ public class JreMemoryLeakPreventionList
     private static final StringManager sm =
         StringManager.getManager(Constants.Package);
 
+    private static final String FORK_JOIN_POOL_THREAD_FACTORY_PROPERTY =
+            "java.util.concurrent.ForkJoinPool.common.threadFactory";
     /**
      * Protect against the memory leak caused when the first call to
      * <code>java.awt.Toolkit.getDefaultToolkit()</code> is triggered
@@ -161,6 +165,19 @@ public class JreMemoryLeakPreventionList
     }
 
     /**
+     * {@link ForkJoinPool#commonPool()} creates a thread pool that, by default,
+     * creates threads that retain references to the thread context class
+     * loader.
+     */
+    private boolean forkJoinCommonPoolProtection = true;
+    public boolean getForkJoinCommonPoolProtection() {
+        return forkJoinCommonPoolProtection;
+    }
+    public void setForkJoinCommonPoolProtection(boolean forkJoinCommonPoolProtection) {
+        this.forkJoinCommonPoolProtection = forkJoinCommonPoolProtection;
+    }
+
+    /**
      * List of comma-separated fully qualified class names to load and initialize during
      * the startup of this Listener. This allows to pre-load classes that are known to
      * provoke classloader leaks if they are loaded during a request processing.
@@ -336,6 +353,17 @@ public class JreMemoryLeakPreventionList
                     }
                 }
 
+                /*
+                 * Present in Java 8 onwards
+                 */
+                if (forkJoinCommonPoolProtection) {
+                    // Don't override any explicitly set property
+                    if (System.getProperty(FORK_JOIN_POOL_THREAD_FACTORY_PROPERTY) == null) {
+                        System.setProperty(FORK_JOIN_POOL_THREAD_FACTORY_PROPERTY,
+                                SafeForkJoinWorkerThreadFactory.class.getName());
+                    }
+                }
+
                 if (classesToInitialize != null) {
                     StringTokenizer strTok =
                         new StringTokenizer(classesToInitialize, ", \r\n\t");

Added: tomcat/trunk/java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java?rev=1778061&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java (added)
+++ tomcat/trunk/java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java Mon Jan  9 21:50:53 2017
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.catalina.startup;
+
+import java.util.concurrent.ForkJoinPool;
+import java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory;
+import java.util.concurrent.ForkJoinWorkerThread;
+
+/**
+ * Provides a {@link ForkJoinWorkerThreadFactory} that provides {@link
+ * ForkJoinWorkerThread}s that won't trigger memory leaks due to retained
+ * references to web application class loaders.
+ * <p>
+ * Note: This class must be available on the boot strap class path for it to be
+ * visible to {@link ForkJoinPool}.
+ */
+public class SafeForkJoinWorkerThreadFactory implements ForkJoinWorkerThreadFactory {
+
+    @Override
+    public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
+        return new SafeForkJoinWorkerThread(pool);
+    }
+
+
+    private static class SafeForkJoinWorkerThread extends ForkJoinWorkerThread {
+
+        protected SafeForkJoinWorkerThread(ForkJoinPool pool) {
+            super(pool);
+            setContextClassLoader(ForkJoinPool.class.getClassLoader());
+        }
+    }
+}
\ No newline at end of file

Propchange: tomcat/trunk/java/org/apache/catalina/startup/SafeForkJoinWorkerThreadFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1778061&r1=1778060&r2=1778061&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Mon Jan  9 21:50:53 2017
@@ -45,6 +45,15 @@
   issues do not "pop up" wrt. others).
 -->
 <section name="Tomcat 9.0.0.M17 (markt)" rtext="in development">
+  <subsection name="Catalina">
+    <changelog>
+      <add>
+        Extend the <code>JreMemoryLeakPreventionListener</code> to provide
+        protection against <code>ForkJoinPool.commonPool()</code> related memory
+        leaks. (markt)
+      </add>
+    </changelog>
+  </subsection>
   <subsection name="Coyote">
     <changelog>
       <fix>

Modified: tomcat/trunk/webapps/docs/config/listeners.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/listeners.xml?rev=1778061&r1=1778060&r2=1778061&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/listeners.xml (original)
+++ tomcat/trunk/webapps/docs/config/listeners.xml Mon Jan  9 21:50:53 2017
@@ -205,6 +205,16 @@
         default is <code>true</code>.</p>
       </attribute>
 
+      <attribute name="forkJoinCommonPoolProtection" required="false">
+        <p>Enables protection so the threads created for
+        <code>ForkJoinPool.commonPool()</code> do not result in a memory leak.
+        The protection is enabled by setting the
+        <code>java.util.concurrent.ForkJoinPool.common.threadFactory</code>
+        system property. If this property is set when Tomcat starts, Tomcat will
+        not over-ride it even if this protection is explictly enabled. The
+        default is <code>true</code>.</p>
+      </attribute>
+
       <attribute name="gcDaemonProtection" required="false">
         <p>Enables protection so that calls to
         <code>sun.misc.GC.requestLatency(long)</code> triggered by a web



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