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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org