Tomcat的ThreadLocalLeakPreventionListener具体是做什么的?

4

org.apache.catalina.core.ThreadLocalLeakPreventionListener的文档说明:

一个 LifecycleListener,在停止 Context 以避免与线程局部变量相关的内存泄漏时触发 Executor 池中线程的续期。

它是如何确切地预防 ThreadLocal 内存泄漏的?在上下文停止时,它是否明确调用 ThreadLocalremove() 方法?

据我所知,ThreadLocal 实现为哈希表。映射键是对 ThreadLocal 实例本身的引用。映射值是线程局部变量值。


2
你尝试过阅读这个源代码了吗? - Frank Pavageau
1个回答

12
首先需要澄清一些问题。当你在应用程序中将某个自定义类放入ThreadLocal中,并在未清除ThreadLocal的情况下卸载/重新部署该应用程序时,就会发生ThreadLocal泄漏。这时,线程仍然持有对您的类的引用,该类又持有对ClassLoader的引用,ClassLoader反过来又持有对您的(已经卸载)Web应用程序加载的所有其他类的引用。
线程仍然持有对象的引用,因为ThreadLocal值实际上是存储在线程内部的。未能清除ThreadLocal意味着这个特定的值将由Thread对象保留,只要它在运行。
现在回到您的问题 - 如果您忘记删除一些ThreadLocal,它将被池线程永久引用。这就是Tomcat试图防止的 - 在怀疑泄漏时关闭并创建新线程。对于Web应用程序而言,这是不可见的,但当您停止池线程并用新线程替换它时,旧线程将成为最后一个引用您的类、类加载器和所有其他内容的对象。最终,您的ThreadLocal值将符合垃圾回收条件。

谢谢您的回复,Tomasz。我只是好奇Tomcat如何“怀疑泄漏”? 它是否监视线程的空闲时间?或者监视线程是否响应、抛出异常等? - Sumit
@Sumit:不幸的是我不知道。但是我猜测在卸载期间它必须检查所有线程池和ThreadLocal - Tomasz Nurkiewicz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接