We are running a high-volume Spring application on Tomcat and seeing steady heap growth. What causes memory leaks in Java applications when using ThreadLocal variables across web server threads, and what is the proper way to clean them up after a request finishes?
3 answers
ThreadLocal variables store data specific to a particular thread. In web application servers like Tomcat, threads are reused via thread pools rather than being destroyed after a request completes. If you set a value in a ThreadLocal and do not explicitly invoke its remove method, that object remains bound to the thread structure indefinitely. Since the thread never dies, the application class loader and the stored objects stay pinned in the heap, causing severe memory degradation across deployments.
Would implementing a global servlet filter that automatically invokes the remove method on all our active ThreadLocals be a safe fix?
Failing to call remove on ThreadLocal variables is one of the quickest ways to break application class loaders during hot redeploys.
Absolutely, Gloria. It leaves heavy garbage behind on every single code refresh, forcing a hard restart of the entire server.
Yes Wayne, a servlet filter or an interceptor is the perfect place for this. By executing the remove call inside the afterCompletion or finally block of the filter, you guarantee the thread is wiped clean before returning to the application pool.