问题
I have the following classes:
public class AppContext {
private static final ThreadLocal<AppContextData> contextHolder = new ThreadLocal<AppContextData>() {
@Override
protected AppContextData initialValue() {
return new AppContextData();
}
};
public static AppContextData get() {
return contextHolder.get();
}
public static void unset() {
contextHolder.remove();
}
}
public class AppContextData {
//many getter and setter methods
}
The website starts using the ThreadLocal object in an interceptor and the object is used through out a web request.
public class MyIntercepter extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
AppContext.get();
//.....
}
}
I run this website on Tomcat 8.x and I find out that the log has the following error message.
How can I fix this issue?
Thanks very much for any input!
20-May-2016 22:43:53.657 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [my.organization.data.AppContext$1] (value [my.organization.data.AppContext$1@31d4463a]) and a value of type [my.organization.data.AppContextData] (value [my.organization.data.AppContextData@e89d5f4]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
回答1:
JanPi already said in the comments what we have to do. In case someone wonders about the how, here it is:
public class MyIntercepter extends HandlerInterceptorAdapter {
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
AppContext.get();
//.....
}
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
AppContext.unset();
}
public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
// only relevant when a handler starts an asynchronous request.
AppContext.unset();
}
}
The postHandle method looks like a good place, but afterCompletion is better because it's called even when the handler fails to process the request correctly (aka an exception occurred).
来源:https://stackoverflow.com/questions/37358426/remove-threadlocal-object-within-a-spring-mvc-website