A ThreadLocal Memory Leak


I’ve seen a lot of MemoryLeaks caused by wrong usage patterns of ThreadLocal variables. As I had this problem in one of our own applications yesterday, I want to blog about this case.

ThreadLocal variables are used in Java to bind a variable to the current Thread – each thread will have its own, independend instance of that variable. These kind of variables are normally used to hold status information like the user, that are needed in the entire application and you don’t want to have in every method signature.

The lifecyle of ThreadLocal variables is directly interconnected to the lifecyle of its corespondig thread. If the thread is terminated and collected by the Garbage Collector, its coresponding ThreadLocal variables will also be good candidates for Garbage Collcetion.

Memory problems will mainly occur if ThreadLocal variables are used inside of Java EE applications running in an application server. Application Servers manage threads by using thread pools to safe resources and boost performance. (See configuration of Tomcat 6 Http Conncector as an example). If for example a HttpServletRequest is send to the ServletEngine of the Application Servers, a free worker thread is taken out of the pool and is associated with the processing of the servlet’s application logic. If the servlet or its called Java classes are using ThreadLocal variables, these variables are associated with the current worker thread. If the servlet is finished and the response is sent to the client, the associated thread is put back to the thread pool, so that it can handle another request. That means that the Thread object and its associated ThreadLocal variables are not garbage collected, as the thread object is still alive.

Depending on the number of threads in the pool (> 100 threads are normal in productive environements) and the size of the object in the ThreadLocal variable, critical memory problems can occur. If for example 200 threads are configured for the thread pool and the ThreadLocal variables are 5MB big, this could result in 1 GB of heaps space occupied by just these ThreadLocal variables. This will lead to an GC overhead and can crash the JVM with an OutOfMemoryError.

In our concrete case the servers had to be restartet every day to avoid OutOfMemoryError problems. To analyse the problem we took a heapdump during runtime (see our recent blog entry how to do this). I did the analysis of the dump with Eclipse MAT which showed very quickly that we had a ThreadLocal memory problem.

The above screenshot shows the Dominator Tree of the dump. I’ve marked 6 Threads each occupying about 14MB of the heap.

The next screenshot shows the details of one of these threads. The high memory consumption is the result of a ThreadLocal variable that references a DOMParser and its parsed document with a total size of 14MB. Because MAT can also show the content of the objects, we could easily see that the parsers were caused by our WebServices. The WebService classes were generated by JBoss WS. Consulting Google showed that this was because of a Bug in jbossws version 1.2.0, which was fixed in 1.2.1: “DOMUtils doesn’t clear thread locals”. So we had to patch our JBoss AppServer with the latest jbossws release and the problem was gone.

This exampe shows that you have to be careful if you use ThreadLocal inside an application server. It is essential to take care that the ThreadLocal variables are dereferenced if they are not used anymore. We normally use ServletFilters to do this job.


  • Sudhir Mongia

    3. September 2010 von Sudhir Mongia

    Good One!! I used ThreadLocal but I was not aware about this fact. good to know.

  • Olivier

    3. September 2010 von Olivier

    Correctly developed there is absolutely no risk in using thread local :

      protected ThreadLocal myThreadLocal = new ThreadLocal();
      public void doFilter (ServletRequest req, ServletResponse res, chain) throws IOException, ServletException {
        try {
          // Set ThreadLocal (eg. to store heavy computation result done only once per request)
          chain.doFilter(req, res);
        } finally {
          // Important : cleanup ThreaLocal to prevent memory leak

    But the new Memory Leak Protection feature introduced in Tomcat 6.0.25 can come handy if you use badly written software 🙂


  • Arun

    I ran into the same problem in a webservice. We had to clear off the threadlocal variables prior to dispatching the response in a interceptor / using AOP.

    I was surprised when I ran into this issue to see that there is a loop hole like this. It will be better if application servers can take care of it so that Threadlocal can be used effectively in Java EE applications.

  • Ashish Kumar

    3. September 2010 von Ashish Kumar

    Very easy to understand and informative. Thanks.

  • Bubak

    I wander if thread pool actually saves that much performance. Maybe just disable it.

  • Endhiran

    7. October 2010 von Endhiran

    Good job. I am running into this memory leak issue because of Threadlocal even in Weblogic 10.3. Surprised that it happens in Weblogic.

  • Christian

    3. December 2014 von Christian

    Is there an easy way to delete (remove) all ThreadLocals if you don’t know their reference (variable name)?

    • Fabian Lange

      The only real way to deal with the issue is either not use ThreadLocals at all (because they just try to bypass code isolation) or use a try/finally pattern to make sure that thread locals are unset after they are set and used.
      Because they are thread local, you can only do that in the thread itself.


Your email address will not be published.