LeakPatterns: ThreadLocal
Another common source of leaks we found was related to the use of ThreadLocal. A ThreadLocal is a way to attach some data to a Thread, so you can get at it later. They are really useful for a couple of cases.
First, you can cache some value (presumably expensive to compute) and reuse it later. Since the value is associated with the Thread, it is thread-safe (baring any issues with the attached objects themselves). This makes the ThreadLocal an important tool in performance optimizations.
Another good use of ThreadLocal is to hold some context-related information. For example, maybe you need some data that is on the HTTP Request (like URLs, attributes, query parameters) in order to make an authorization decision for access to certain data. Normally, this would mean that all that data (or the Request itself) would need to appear on the authorizer API - and on any API that called that one - and on any API calling those APIs, etc. Or, you could toss the Request data into a ThreadLocal and retrieve it in the authorizer. It becomes context for the call to the authorizer. This is another really useful technique for loosely tying subsystems together.
But in a server environment (like WebLogic), the Threads are usually pooled and reused for request after request. The ThreadLocal is associated with a Thread, and the Thread is associated with a Request - so that is good. Except that the Thread is only temporarily associated with the Request.
So, if ThreadLocal objects are not managed correctly (such that their life-cycle matches that of the Request), you can get all sorts of evil things happening. First, if you were using ThreadLocal for performance, it just might not work since one user session might be handled by many different Threads. Worse, you might leak data from one user to another (when a user’s Request reuses a Thread containing another user’s data).
And in the cases I saw, if that ThreadLocal holds objects that otherwise should be garbage collected, you will get a leak.
The solution is to ensure that your ThreadLocal usages are properly managed. The ThreadLocal should have the same life cycle as the Request, and you should use ThreadLocal.remove() – preferably in a proper finally block - to clean up at the end of your Request.
Technorati Tags: leak, memory, portal, ThreadLocal, WebLogic
1 Comment so far
Leave a reply
Very interesting post Dave. I have used ThreadLocal before to hold context data as you mention in the post to avoid having to pass a context object throughout the application. I was going to use it again in another app but this time the application is deployed on a clustered weblogic 10 environment and has some stateless session beans (SLSBs) handling the business logic & calling other SLSBs & data access. Your post got me thinking - can a ThreadLocal even keep track of a request in such an application?
In the course of processing a request, more than one thread could be involved. E.g. the first SLSB is executed by thread A and then calls another SLSB and that is executed by thread B (by the other server in the cluster). Does Weblogic keep track of (and propagate) ThreadLocals across the cluster .. ? Is using ThreadLocals even feasible in this scenario?