Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Threads ContextClassLoader

Threads spawned by

...

webapps

If a webapp creates a thread, by default its context classloader is set to the one of the parent thread (the thread that created the new thread). In a webapp, this parent thread is one of tomcat worker threads, whose context classloader is set to the webapp classloader when it executes webapp code.

Furthermore, the spawned thread may be executing (or blocked in) some code that involves classes loaded by the webapp, thus preventing the webapp classloader from being collected.

So, if the spawned thread is not properly terminated when the application is stopped, the webapp classloader will leak because of the strong reference held by the spawned thread.

Example :

No Format

public class LeakingServlet extends HttpServlet {
	private Thread leakingThread;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		if (leakingThread == null) {
			synchronized (this) {
				if (leakingThread == null) {
					leakingThread = new Thread("leakingThread") {

						@Override
						public void run() {
							synchronized (this) {
								try {
									this.wait();
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}
						}
					};
					leakingThread.setDaemon(true);
					//leakingThread.setContextClassLoader(null);
					leakingThread.start();
				}
			}
		}
		response.getWriter().println("Hello world!");
	}
}

Here, when the app is stopped, the webapp classloader is still referenced by the spawned thread both through its context classloader and its current call stack (the anonymous Thread subclass is loaded by the webapp classloader).

When stopping an application, tomcat checks the context classloader of every Thread, and if it is the same as the app being stopped, it logs the following message :

No Format

Mar 18, 2010 11:13:07 PM org.apache.catalina.core.ApplicationContext log
INFO: HTMLManager: stop: Stopping web application at '/testWeb'
Mar 18, 2010 11:13:07 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [leakingThread] but has failed to stop it. This is very likely to create a memory leak.

Now, if we uncomment the line leakingThread.setContextClassLoader(null); in the above example, tomcat (6.0.24) no longer detect the leak when the application is stopped because the spawned thread context classloader is no longer the webapp's. (the "Find leaks" feature in the manager will report it though)

Threads spawned by classes loaded by the common classloader

TODO : example with the Evictor thread of dbcp

Threads spawned by

...

JRE classes

Child classloaders

static class variables

...

JDBC driver registration

RMI target

Summary matrix

Leak type

Detected by tomcat

Fixed by tomcat

Possible enhancements

...

References

Related issues

  • 48837 - Memory leaks protection does not cure leaks triggered by JSP pages code