原博:http://java.jiderhamn.se/2012/01/29/classloader-leaks-iv-threadlocal-dangers-and-why-threadglobal-may-have-been-a-more-appropriate-name
以下记录,主要是为了以后复习使用。
1.Thread Local 引起的Classloader leaks
ThreadLocal主要是解决在多线程中,实现线程变量安全的方法
ThreadLocal使用后,需要删除,如果没有删除,会导致ThreadLocal无法回收,它内部使用了ThreadLocalMap,这个Map在jvm中是软引用,不一定会被回收(只有在内存紧张的时候会回收)
try {
threadLocal.set(value);
...
}
finally {
threadLocal.remove();
}
2.解决这个问题可以使用Servlet过滤器
public class ThreadLocalLeakPreventionFilter implements javax.servlet.Filter {
private ThreadLocal[] offendingThreadLocals;
public void init(FilterConfig filterConfig) throws ServletException {
List<ThreadLocal> threadLocals = new ArrayList<ThreadLocal>();
// TODO: Needs error handling!!!
Class clazz = Class.forName("org.apache.axis.utils.XMLUtils");
if(clazz != null) {
final Field threadLocalField =
clazz.getDeclaredField("documentBuilder");
if(threadLocalField != null) {
threadLocalField.setAccessible(true);
Object threadLocal = threadLocalField.get(null);
if(threadLocal instanceof ThreadLocal) {
threadLocals.add((ThreadLocal)threadLocal);
}
}
}
// TODO: Look up more offenders here
this.offendingThreadLocals =
threadLocals.toArray(new ThreadLocal[threadLocals.size()]);
}
/**
* In the doFilter() method we have a chance to clean up the thread
* before it is returned to the thread pool
*/
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain)
throws IOException, ServletException {
try {
filterChain.doFilter(servletRequest, servletResponse);
}
finally {
// Clean up ThreadLocals
for(ThreadLocal offendingThreadLocal : offendingThreadLocals) {
offendingThreadLocal.remove(); // Remove offender from current thread
}
}
}
public void destroy() {
offendingThreadLocals = null; // Make available for Garbage Collector
}
-->
}