Author: markt Date: Mon Dec 16 20:39:19 2013 New Revision: 1551340 URL: http://svn.apache.org/r1551340 Log: Performance improvement The context class loader was set in *Endpoint#processSocket() in case a new thread was created since this method may be triggered from web application code and that in turn would trigger a memory leak since the thread would end up with the web app class loader as its context class loader. However, this is only an issue when creating threads and since getting the current class loader is expensive, move this code to where threads are created rather than calling it on every call to *Endpoint#processSocket(). This appears (on my fairly unscientific tests) to remove ~5% of the overhead from all request processing.
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Mon Dec 16 20:39:19 2013 @@ -20,7 +20,6 @@ import java.io.File; import java.io.OutputStreamWriter; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -97,22 +96,6 @@ public abstract class AbstractEndpoint<S } - protected static class PrivilegedSetTccl implements PrivilegedAction<Void> { - - private ClassLoader cl; - - PrivilegedSetTccl(ClassLoader cl) { - this.cl = cl; - } - - @Override - public Void run() { - Thread.currentThread().setContextClassLoader(cl); - return null; - } - } - - private static final int INITIAL_ERROR_DELAY = 50; private static final int MAX_ERROR_DELAY = 1600; Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Mon Dec 16 20:39:19 2013 @@ -17,8 +17,6 @@ package org.apache.tomcat.util.net; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -892,26 +890,7 @@ public class AprEndpoint extends Abstrac SocketProcessor proc = new SocketProcessor(socket, status); Executor executor = getExecutor(); if (dispatch && executor != null) { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - try { - //threads should not be created by the webapp classloader - if (Constants.IS_SECURITY_ENABLED) { - PrivilegedAction<Void> pa = new PrivilegedSetTccl( - getClass().getClassLoader()); - AccessController.doPrivileged(pa); - } else { - Thread.currentThread().setContextClassLoader( - getClass().getClassLoader()); - } - executor.execute(proc); - } finally { - if (Constants.IS_SECURITY_ENABLED) { - PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader); - AccessController.doPrivileged(pa); - } else { - Thread.currentThread().setContextClassLoader(loader); - } - } + executor.execute(proc); } else { proc.run(); } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Mon Dec 16 20:39:19 2013 @@ -22,8 +22,6 @@ import java.net.BindException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; @@ -566,31 +564,11 @@ public class JIoEndpoint extends Abstrac SocketProcessor proc = new SocketProcessor(socket,status); Executor executor = getExecutor(); if (dispatch && executor != null) { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - try { - //threads should not be created by the webapp classloader - if (Constants.IS_SECURITY_ENABLED) { - PrivilegedAction<Void> pa = - new PrivilegedSetTccl( - getClass().getClassLoader()); - AccessController.doPrivileged(pa); - } else { - Thread.currentThread().setContextClassLoader( - getClass().getClassLoader()); - } - // During shutdown, executor may be null - avoid NPE - if (!running) { - return; - } - getExecutor().execute(proc); - } finally { - if (Constants.IS_SECURITY_ENABLED) { - PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader); - AccessController.doPrivileged(pa); - } else { - Thread.currentThread().setContextClassLoader(loader); - } + // During shutdown, executor may be null - avoid NPE + if (!running) { + return; } + getExecutor().execute(proc); } else { proc.run(); } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1551340&r1=1551339&r2=1551340&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Mon Dec 16 20:39:19 2013 @@ -32,8 +32,6 @@ import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.WritableByteChannel; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Iterator; import java.util.Set; import java.util.concurrent.CountDownLatch; @@ -631,26 +629,7 @@ public class NioEndpoint extends Abstrac else sc.reset(socket,status); Executor executor = getExecutor(); if (dispatch && executor != null) { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - try { - //threads should not be created by the webapp classloader - if (Constants.IS_SECURITY_ENABLED) { - PrivilegedAction<Void> pa = new PrivilegedSetTccl( - getClass().getClassLoader()); - AccessController.doPrivileged(pa); - } else { - Thread.currentThread().setContextClassLoader( - getClass().getClassLoader()); - } - executor.execute(sc); - } finally { - if (Constants.IS_SECURITY_ENABLED) { - PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader); - AccessController.doPrivileged(pa); - } else { - Thread.currentThread().setContextClassLoader(loader); - } - } + executor.execute(sc); } else { sc.run(); } @@ -872,7 +851,7 @@ public class NioEndpoint extends Abstrac private volatile boolean close = false; private long nextExpiration = 0;//optimize expiration handling - private AtomicLong wakeupCounter = new AtomicLong(0l); + private AtomicLong wakeupCounter = new AtomicLong(0); private volatile int keyCount = 0; Modified: tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java?rev=1551340&r1=1551339&r2=1551340&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/threads/TaskThreadFactory.java Mon Dec 16 20:39:19 2013 @@ -16,19 +16,24 @@ */ package org.apache.tomcat.util.threads; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.tomcat.util.net.Constants; /** - * Simple task thread factory to use to create threads for an executor implementation. - * @author fhanik - * + * Simple task thread factory to use to create threads for an executor + * implementation. */ public class TaskThreadFactory implements ThreadFactory { + private final ThreadGroup group; private final AtomicInteger threadNumber = new AtomicInteger(1); private final String namePrefix; private final boolean daemon; private final int threadPriority; + public TaskThreadFactory(String namePrefix, boolean daemon, int priority) { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); @@ -39,10 +44,44 @@ public class TaskThreadFactory implement @Override public Thread newThread(Runnable r) { - TaskThread t = new TaskThread(group, r, namePrefix + threadNumber.getAndIncrement()); - t.setDaemon(daemon); - t.setPriority(threadPriority); - return t; + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + try { + // Threads should not be created by the webapp classloader + if (Constants.IS_SECURITY_ENABLED) { + PrivilegedAction<Void> pa = new PrivilegedSetTccl( + getClass().getClassLoader()); + AccessController.doPrivileged(pa); + } else { + Thread.currentThread().setContextClassLoader( + getClass().getClassLoader()); + } + TaskThread t = new TaskThread(group, r, namePrefix + threadNumber.getAndIncrement()); + t.setDaemon(daemon); + t.setPriority(threadPriority); + return t; + } finally { + if (Constants.IS_SECURITY_ENABLED) { + PrivilegedAction<Void> pa = new PrivilegedSetTccl(loader); + AccessController.doPrivileged(pa); + } else { + Thread.currentThread().setContextClassLoader(loader); + } + } } + + private static class PrivilegedSetTccl implements PrivilegedAction<Void> { + + private ClassLoader cl; + + PrivilegedSetTccl(ClassLoader cl) { + this.cl = cl; + } + + @Override + public Void run() { + Thread.currentThread().setContextClassLoader(cl); + return null; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org