有没有人有如何做到这一点的例子?它们是由垃圾收集器处理的吗?我正在使用 Tomcat 6。
原文由 Ricardo 发布,翻译遵循 CC BY-SA 4.0 许可协议
有没有人有如何做到这一点的例子?它们是由垃圾收集器处理的吗?我正在使用 Tomcat 6。
原文由 Ricardo 发布,翻译遵循 CC BY-SA 4.0 许可协议
当您没有对实际线程局部变量的引用时,这里有一些代码可以清除当前线程中的所有线程局部变量。您还可以将其概括为为其他线程清理线程局部变量:
private void cleanThreadLocals() {
try {
// Get a reference to the thread locals table of the current thread
Thread thread = Thread.currentThread();
Field threadLocalsField = Thread.class.getDeclaredField("threadLocals");
threadLocalsField.setAccessible(true);
Object threadLocalTable = threadLocalsField.get(thread);
// Get a reference to the array holding the thread local variables inside the
// ThreadLocalMap of the current thread
Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap");
Field tableField = threadLocalMapClass.getDeclaredField("table");
tableField.setAccessible(true);
Object table = tableField.get(threadLocalTable);
// The key to the ThreadLocalMap is a WeakReference object. The referent field of this object
// is a reference to the actual ThreadLocal variable
Field referentField = Reference.class.getDeclaredField("referent");
referentField.setAccessible(true);
for (int i=0; i < Array.getLength(table); i++) {
// Each entry in the table array of ThreadLocalMap is an Entry object
// representing the thread local reference and its value
Object entry = Array.get(table, i);
if (entry != null) {
// Get a reference to the thread local object and remove it from the table
ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry);
threadLocal.remove();
}
}
} catch(Exception e) {
// We will tolerate an exception here and just log it
throw new IllegalStateException(e);
}
}
原文由 lyaffe 发布,翻译遵循 CC BY-SA 3.0 许可协议
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4.1k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
javadoc 是这样说的:
如果您的应用程序或(如果您正在谈论请求线程)容器使用线程池,这意味着线程不会死亡。如有必要,您需要自己处理线程局部变量。唯一干净的方法是调用
ThreadLocal.remove()
方法。您可能希望为线程池中的线程清理线程局部变量的原因有两个:
线程局部内存泄漏通常不应该是有界线程池的主要问题,因为任何线程局部内存最终都可能被覆盖;即当线程被重用时。但是,如果您错误地一遍又一遍地创建新的
ThreadLocal
实例(而不是使用static
变量来保存单例实例),线程本地值将不会被覆盖,并将累积在每个线程的threadlocals
映射中。这可能会导致严重泄漏。假设您正在谈论在 webapp 处理 HTTP 请求期间创建/使用的线程局部变量,那么避免线程局部泄漏的一种方法是注册一个
ServletRequestListener
与您的 webapp 的ServletContext
并实现侦听器的requestDestroyed
方法来清除当前线程的线程局部变量。请注意,在这种情况下,您还需要考虑 信息 从一个请求泄漏到另一个请求的可能性。