Classloader leaks
原博: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 } --> }