Why can ThreadLocal cause memory leaks in Java applications?

Did you know that ThreadLocal can cause memory leaks in Java applications? Yes, it can! The problem isn’t with ThreadLocal itself, but with improper use of thread pools.

When you call the set() method of a ThreadLocal, the value is held within the current thread. If that thread completes its task, the Garbage Collector collects it.

But with a thread pool, the thread doesn’t get removed. It’s reused to process other tasks.

Imagine request A stores the UserContext in a ThreadLocal object. After this request completes, the thread is returned to the pool. If you forget to call the remove() method to remove the UserContext object, it will always remain with the thread. If this thread handles another request B, the old value of the UserContext object will still exist. This isn’t just about our application storing an unnecessary object in memory; it’s also about data from this task leaking to other tasks!

The solution is extremely simple: just remember to clean up the ThreadLocal object using the remove() method after the task is complete.

You can use a try-finally block:

For example:

In this example, as you can see, after performing the task, I called the remove() method in the try-finally block to remove the value in ThreadLocal.

Result:

Remember: If you call the set() method, remember to also call the remove() method, especially when using a thread pool with ExecutorService or web servers like Apache Tomcat.

Add Comment