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 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.
Tidak ada komentar:
Posting Komentar