Monday, January 14, 2013

ThreadLocal Memory Leak in Java web application - Tomcat

ThreadLocal variables are infamous for creating memory leaks. A memory leak in Java is amount of memory hold by object which are not in use and should have been garbage collected, but because of unintended strong references, they still live in Java heap space. There are many ways memory leak can be caused in Java but when this memory leak is caused due to ThreadLocal variable, it’s refereed as ThreadLocal memory leak. In our last post about ThreadLocal variable, we have seen How ThreadLocal variable can make SimpleDateFormat thread-safe and also raised point that in managed environment like J2EE application server or web server like Tomcat, Jetty, WebSphere or Weblogic use of ThreadLocal should be avoided. In this post we will go little deep and find out How ThreadLocal variables creates memory leak in Java web application, much like we have seen How to fix PermGen memory leak in Tomcat. If you are not familiar with ThreadLocal variables I suggest to go through my previous post. Before going into detail let's recap How ThreadLocal class works in Java.


How ThreadLocal works in Java :
ThreadLocal memory leak in Java web application in tomcatThreadLocal in Java is a mechanism to provide separate copy of shared object to every Thread. So that they no longer shared between multiple Threads and remain thread-safe. ThreadLocal variables are stored in a special map called ThreadLocalMap which is designed to hold thread local objects, it uses WeakReferences for keys. Since every Thread has strong reference to there copy of ThreadLocal variables, they are not garbage collected until Thread is Alive and this is what creates memory leak in a typical J2EE web application. This is explained in detail in next section “How ThreadLocal variable creates memory leak in Java”.

How ThreadLocal creates memory leak in Java

In web server and application server like Tomcat or WebLogic, web-app is loaded by a different ClassLoader than which is used by Server itself. This ClassLoader loads and unloads classes from web application. Web servers also maintains ThreadPool, which is collection of worker thread, to server HTTP requests. Now if one of the Servlet or any other Java class from web application creates a ThreadLocal variable during request processing and doesn't remove it after that, copy of that Object will remain with worker Thread and since life-span of worker Thread is more than web app itself, it will prevent the object and ClassLoader, which uploaded the web app, from being garbage collected. This will create a memory leak in Server. Now if you do this couple of time you may see java.lang.OutOfMemoryError: PermGen space . Now this brings an important question,  is it possible to to use ThreadLocal variable safely in a managed environment?  Answer is Yes,, but that requires a careful usage of ThreadLocal variable and making sure to remove the object from ThreadLocal once done.

How to use ThreadLocal safely in Java Web application
Many people use Filters to initialize and remove ThreadLocal variables. You can initialize ThreadLocal in filter, put some expensive object as ThreadLocal and once request has been processed remove it from ThreadLocal as shown in below example:

public void doFilter(ServeletRequest request, ServletResponse){
        try{

          //set ThreadLocal variable
        chain.doFilter(request, response)

        }finally{
          //remove threadLocal variable.
        }
}

That’s all on How ThreadLocal variable creates memory leak in Java. Having said that, If not necessary or You can manage without ThreadLocal variable than it’s best to avoid using ThreadLocal in managed environments like J2EE web and application servers.

5 comments :

Anonymous said...

Could you explain why it causes the memory leak ? The variable is removed from the ThreadLocal at evey request, so it should prevent memory leaking.

Anonymous said...

"are not garbage collected until Thread is Alive"
Don't you mean "Dead"

Regards
Ren

Javin @ What is Inheritance in Java said...

@Anonymous, yes if you remove ThreadLocal at every request that it won't cause memory leak. Memory leak caused when you forget to remove ThreadLocal variable once done.

Anonymous said...

Just to add on what Javin said, Yes this is true that threadlocal variables can prevent a class and subsequently classloader which is loaded them from being garbage collected, but this will only create issue if you store application classes in ThreadLocal, which is loaded by web-app classloader. If you store classes from JDK e.g. SimpleDateFormat, it will not create memory leak in Java web application, because they are loaded by BootStrap classloader, so they are not reloaded each time you deploy and un-deploy your web application. Having said that, it's best practice to remove any variable from thread local, as soon as you are done with that. For example if you are storing user specific information e.g. username as threadlocal in Filter class than you can also remove them, once request is processed.

Anonymous said...

If your server is pooling the threads then in that case it will create the memory leak. Basically after serving your request, thread will be returned to the pool(not dead) . So, the thread local object will be associated with the thread even after the utility of it. So, best way is to remove the thread local object from the thread as soon as you are finished with it.

Post a Comment