Is it worth cleaning ThreadLocals in Filter to solve thread pool-related issues?
In short - tomcat uses a thread pool, so threads are reused. Some libraries use ThreadLocal
variables, but don't clean them up (using .remove()
), so in fact they return "dirty" threads to the pool.
Tomcat has new features of detecting these things on shutdown, and cleaning the thread locals. But it means the threads are "dirty" during the whole execution.
What I can do is implement a Filter
, and right after the re开发者_如何学Cquest completes (and the thread is returned to the pool), clean all ThreadLocal
s, using the code from tomcat (the method there is called checkThreadLocalsForLeaks
).
The question is, is it worth it? Two pros:
- preventing memory leaks
- preventing undeterministic behaviour by the libraries, which assume the thread is "fresh"
One con:
- The solution uses reflection, so it's potentially slow. All reflection data (
Field
s) will be cached, of course, but still.
Another option is to report the issue to the libraries that don't clean their thread locals.
I would go through the route of reporting the issue to the library developers for 2 reasons:
- It will help to other people who want to use the same library, but lack the skills / time to find such a HORRIBLE memory leak.
- To help the developers of the library to build a better product.
Honestly, I've never seen this type of error before and I think it's an exception rather than something that we should guard as it happens often. Could you share on which library you've seen this behaviour?
As a side note, I wouldn't mind enabling that filter in the development / test environment and logging a critical error if a ThreadLocal variable is still attached.
in theory, this seems like a good idea. however, i could see some situations where you might not want to do this. for instance, some of the xml related technologies have some non-trivial setup costs (like setting up DocumentBuilders and Transformers). if you are doing a lot of that in your webapp, it may make sense to cache these instances in ThreadLocals (as the utilities are generally not thread-safe). in this case, you probably don't want to clean these between requests.
If you think there's a chance that the dirtiness of the threads will actually cause problems, then this is a sensible thing to do. Problems are to be avoided where possible.
The use of threadlocals may be bad behaviour by the library, and you should certainly report it to the authors, but sadly, right now, it's down to you to deal with it.
I wouldn't worry too much about performance. The slow bit in reflection is the metadata lookup; once you have a Field object, then using it is fairly quick, and gets quicker over time - AIUI, it starts out working by making a native call into the JVM, but after some number of uses, it generates bytecode for the access, which can then be compiled into native code, optimised, inlined, etc, so it shouldn't be much slower than a direct field access. I don't think the Tomcat code reuses the Field objects across requests, though, so if you want to take advantage of that, you'd have to write your own cleaning code. In any case, the performance cost will be far smaller than the cost of the IO associated with the request.
精彩评论