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 2010/02/08 13:57:08 UTC

svn commit: r907646 - in /tomcat/trunk/test/org/apache/catalina/loader: ./ TestWebappClassLoaderMemoryLeak.java

Author: markt
Date: Mon Feb  8 12:57:08 2010
New Revision: 907646

URL: http://svn.apache.org/viewvc?rev=907646&view=rev
Log:
Add a test case for TimerThread thread/memory leaks on reload as I have some ideas on how to safely terminate those threads

Added:
    tomcat/trunk/test/org/apache/catalina/loader/
    tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java   (with props)

Added: tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java?rev=907646&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java (added)
+++ tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java Mon Feb  8 12:57:08 2010
@@ -0,0 +1,94 @@
+package org.apache.catalina.loader;
+
+import java.io.IOException;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.catalina.core.StandardContext;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+
+public class TestWebappClassLoaderMemoryLeak extends TomcatBaseTest {
+
+    public void testTimerThreadLeak() throws Exception {
+        Tomcat tomcat = getTomcatInstance();
+        
+        // Must have a real docBase - just use temp
+        StandardContext ctx = 
+            tomcat.addContext("/", System.getProperty("java.io.tmpdir"));
+        
+        Tomcat.addServlet(ctx, "taskServlet", new TaskServlet());
+        ctx.addServletMapping("/", "taskServlet");
+        
+        tomcat.start();
+
+        // This will trigger the timer & thread creation
+        getUrl("http://localhost:" + getPort() + "/");
+        
+        // Stop the context
+        ctx.stop();
+        
+        // If the thread still exists, we have a thread/memory leak
+        Thread[] threads = getThreads();
+        for (Thread thread : threads) {
+            if (thread.getName().equals(TaskServlet.TIMER_THREAD_NAME)) {
+                fail("Timer thread still running");
+            }
+        }
+    }
+    
+    /*
+     * Get the set of current threads as an array.
+     * Copied from WebappClassLoader
+     */
+    private Thread[] getThreads() {
+        // Get the current thread group 
+        ThreadGroup tg = Thread.currentThread( ).getThreadGroup( );
+        // Find the root thread group
+        while (tg.getParent() != null) {
+            tg = tg.getParent();
+        }
+        
+        int threadCountGuess = tg.activeCount() + 50;
+        Thread[] threads = new Thread[threadCountGuess];
+        int threadCountActual = tg.enumerate(threads);
+        // Make sure we don't miss any threads
+        while (threadCountActual == threadCountGuess) {
+            threadCountGuess *=2;
+            threads = new Thread[threadCountGuess];
+            // Note tg.enumerate(Thread[]) silently ignores any threads that
+            // can't fit into the array 
+            threadCountActual = tg.enumerate(threads);
+        }
+        
+        return threads;
+    }
+
+    private static final class TaskServlet extends HttpServlet {
+
+        private static final long serialVersionUID = 1L;
+        private static final String TIMER_THREAD_NAME = "leaked-thread";
+
+        @Override
+        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                throws ServletException, IOException {
+            Timer timer = new Timer(TIMER_THREAD_NAME);
+            timer.schedule(new LocalTask(), 0, 10000);
+        }
+        
+    }
+
+    private static final class LocalTask extends TimerTask {
+
+        @Override
+        public void run() {
+            // Doesn't actually need to do anything.
+        }
+        
+    }
+}

Propchange: tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: tomcat/trunk/test/org/apache/catalina/loader/TestWebappClassLoaderMemoryLeak.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision



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