use of org.apache.tomcat.util.threads.ThreadPoolExecutor in project tomcat70 by apache.
the class TestWebappClassLoaderThreadLocalMemoryLeak method testThreadLocalLeak1.
@Test
public void testThreadLocalLeak1() throws Exception {
Tomcat tomcat = getTomcatInstance();
// Need to make sure we see a leak for the right reasons
tomcat.getServer().addLifecycleListener(new JreMemoryLeakPreventionListener());
// No file system docBase required
Context ctx = tomcat.addContext("", null);
Tomcat.addServlet(ctx, "leakServlet1", "org.apache.tomcat.unittest.TesterLeakingServlet1");
ctx.addServletMapping("/leak1", "leakServlet1");
tomcat.start();
Executor executor = tomcat.getConnector().getProtocolHandler().getExecutor();
((ThreadPoolExecutor) executor).setThreadRenewalDelay(-1);
// Configure logging filter to check leak message appears
TesterLogValidationFilter f = TesterLogValidationFilter.add(null, "The web application [] created a ThreadLocal with key of", null, "org.apache.catalina.loader.WebappClassLoaderBase");
// Need to force loading of all web application classes via the web
// application class loader
loadClass("TesterCounter", (WebappClassLoaderBase) ctx.getLoader().getClassLoader());
loadClass("TesterLeakingServlet1", (WebappClassLoaderBase) ctx.getLoader().getClassLoader());
// This will trigger the ThreadLocal creation
int rc = getUrl("http://localhost:" + getPort() + "/leak1", new ByteChunk(), null);
// Make sure request is OK
Assert.assertEquals(HttpServletResponse.SC_OK, rc);
// Destroy the context
ctx.stop();
tomcat.getHost().removeChild(ctx);
ctx = null;
// Make sure we have a memory leak
String[] leaks = ((StandardHost) tomcat.getHost()).findReloadedContextMemoryLeaks();
Assert.assertNotNull(leaks);
Assert.assertTrue(leaks.length > 0);
// Make sure the message was logged
Assert.assertEquals(1, f.getMessageCount());
}
use of org.apache.tomcat.util.threads.ThreadPoolExecutor in project tomcat70 by apache.
the class StandardThreadExecutor method startInternal.
/**
* Start the component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
taskqueue = new TaskQueue(maxQueueSize);
TaskThreadFactory tf = new TaskThreadFactory(namePrefix, daemon, getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS, taskqueue, tf);
executor.setThreadRenewalDelay(threadRenewalDelay);
if (prestartminSpareThreads) {
executor.prestartAllCoreThreads();
}
taskqueue.setParent(executor);
setState(LifecycleState.STARTING);
}
use of org.apache.tomcat.util.threads.ThreadPoolExecutor in project tomcat by apache.
the class StandardThreadExecutor method startInternal.
/**
* Start the component and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
taskqueue = new TaskQueue(maxQueueSize);
TaskThreadFactory tf = new TaskThreadFactory(namePrefix, daemon, getThreadPriority());
executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS, taskqueue, tf);
executor.setThreadRenewalDelay(threadRenewalDelay);
if (prestartminSpareThreads) {
executor.prestartAllCoreThreads();
}
taskqueue.setParent(executor);
setState(LifecycleState.STARTING);
}
use of org.apache.tomcat.util.threads.ThreadPoolExecutor in project tomcat by apache.
the class AsyncChannelGroupUtil method createAsynchronousChannelGroup.
private static AsynchronousChannelGroup createAsynchronousChannelGroup() {
// Need to do this with the right thread context class loader else the
// first web app to call this will trigger a leak
ClassLoader original = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(AsyncIOThreadFactory.class.getClassLoader());
// These are the same settings as the default
// AsynchronousChannelGroup
int initialSize = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, Long.MAX_VALUE, TimeUnit.MILLISECONDS, new SynchronousQueue<>(), new AsyncIOThreadFactory());
try {
return AsynchronousChannelGroup.withCachedThreadPool(executorService, initialSize);
} catch (IOException e) {
// No good reason for this to happen.
throw new IllegalStateException(sm.getString("asyncChannelGroup.createFail"));
}
} finally {
Thread.currentThread().setContextClassLoader(original);
}
}
use of org.apache.tomcat.util.threads.ThreadPoolExecutor in project tomcat by apache.
the class WebappClassLoaderBase method clearReferencesThreads.
// thread.stop()
@SuppressWarnings("deprecation")
private void clearReferencesThreads() {
Thread[] threads = getThreads();
List<Thread> threadsToStop = new ArrayList<>();
// Iterate over the set of threads
for (Thread thread : threads) {
if (thread != null) {
ClassLoader ccl = thread.getContextClassLoader();
if (ccl == this) {
// Don't warn about this thread
if (thread == Thread.currentThread()) {
continue;
}
final String threadName = thread.getName();
// JVM controlled threads
ThreadGroup tg = thread.getThreadGroup();
if (tg != null && JVM_THREAD_GROUP_NAMES.contains(tg.getName())) {
// HttpClient keep-alive threads
if (clearReferencesHttpClientKeepAliveThread && threadName.equals("Keep-Alive-Timer")) {
thread.setContextClassLoader(parent);
log.debug(sm.getString("webappClassLoader.checkThreadsHttpClient"));
}
// Don't warn about remaining JVM controlled threads
continue;
}
// Skip threads that have already died
if (!thread.isAlive()) {
continue;
}
// "java.util.Timer$TimerImpl" in Apache Harmony and in IBM JDK
if (thread.getClass().getName().startsWith("java.util.Timer") && clearReferencesStopTimerThreads) {
clearReferencesStopTimerThread(thread);
continue;
}
if (isRequestThread(thread)) {
log.warn(sm.getString("webappClassLoader.stackTraceRequestThread", getContextName(), threadName, getStackTrace(thread)));
} else {
log.warn(sm.getString("webappClassLoader.stackTrace", getContextName(), threadName, getStackTrace(thread)));
}
// configured to do so
if (!clearReferencesStopThreads) {
continue;
}
// If the thread has been started via an executor, try
// shutting down the executor
boolean usingExecutor = false;
try {
// Runnable wrapped by Thread
// "target" in Sun/Oracle JDK
// "runnable" in IBM JDK
// "action" in Apache Harmony
Object target = null;
for (String fieldName : new String[] { "target", "runnable", "action" }) {
try {
Field targetField = thread.getClass().getDeclaredField(fieldName);
targetField.setAccessible(true);
target = targetField.get(thread);
break;
} catch (NoSuchFieldException nfe) {
continue;
}
}
// internal fork.
if (target != null && target.getClass().getCanonicalName() != null && (target.getClass().getCanonicalName().equals("org.apache.tomcat.util.threads.ThreadPoolExecutor.Worker") || target.getClass().getCanonicalName().equals("java.util.concurrent.ThreadPoolExecutor.Worker"))) {
Field executorField = target.getClass().getDeclaredField("this$0");
executorField.setAccessible(true);
Object executor = executorField.get(target);
if (executor instanceof ThreadPoolExecutor) {
((ThreadPoolExecutor) executor).shutdownNow();
usingExecutor = true;
} else if (executor instanceof java.util.concurrent.ThreadPoolExecutor) {
((java.util.concurrent.ThreadPoolExecutor) executor).shutdownNow();
usingExecutor = true;
}
}
} catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException | InaccessibleObjectException e) {
log.warn(sm.getString("webappClassLoader.stopThreadFail", thread.getName(), getContextName()), e);
}
// them here.
if (!usingExecutor && !thread.isInterrupted()) {
thread.interrupt();
}
// Threads are expected to take a short time to stop after
// being interrupted. Make a note of all threads that are
// expected to stop to enable them to be checked at the end
// of this method.
threadsToStop.add(thread);
}
}
}
// If thread stopping is enabled, threads should have been stopped above
// when the executor was shut down or the thread was interrupted but
// that depends on the thread correctly handling the interrupt. Check
// each thread and if any are still running give all threads up to a
// total of 2 seconds to shutdown.
int count = 0;
for (Thread t : threadsToStop) {
while (t.isAlive() && count < 100) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// Quit the while loop
break;
}
count++;
}
if (t.isAlive()) {
// This method is deprecated and for good reason. This is
// very risky code but is the only option at this point.
// A *very* good reason for apps to do this clean-up
// themselves.
t.stop();
}
}
}
Aggregations