在tomcat7下停止应用时报错:created a ThreadLocal with key of type

Tomcat7应用停止时的ThreadLocal内存泄漏问题与解决方案
在停止Tomcat7应用程序时遇到了一个错误,提示创建了一个类型为com.opensymphony.xwork2.inject.ContainerImpl$10的ThreadLocal。此问题可能导致内存泄漏。解决方案包括升级xwork的jar文件到2.3.3以上版本或修改并替换ContainerImpl类以消除警告。通过这些措施,可以避免潜在的内存泄漏问题。

在tomcat7下停止应用时报错: created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$10]

INFO: A valid shutdown command was received via the shutdown port. Stopping the Server instance.
Apr 02, 2015 10:36:52 AM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["http-bio-8080"]
Apr 02, 2015 10:36:52 AM org.apache.coyote.AbstractProtocol pause
INFO: Pausing ProtocolHandler ["ajp-bio-8009"]
Apr 02, 2015 10:36:52 AM org.apache.catalina.core.StandardService stopInternal
INFO: Stopping service Catalina
Apr 02, 2015 10:36:52 AM org.apache.catalina.core.ApplicationContext log
INFO: Closing Spring root WebApplicationContext
Apr 02, 2015 10:36:52 AM org.apache.catalina.loader.WebappClassLoader checkThreadLocalMapForLeaks
SEVERE: The web application [/techrevmanager5] created a ThreadLocal with key of type [com.opensymphony.xwork2.inject.ContainerImpl$3] (value [com.opensymphony.xwork2.inject.ContainerImpl$3@49860b6d]) and a value of type [java.lang.Object[]] (value [[Ljava.lang.Object;@7f5846d0]) 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.
Apr 02, 2015 10:36:52 AM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["http-bio-8080"]
Apr 02, 2015 10:36:52 AM org.apache.coyote.AbstractProtocol stop
INFO: Stopping ProtocolHandler ["ajp-bio-8009"]
Apr 02, 2015 10:36:52 AM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["http-bio-8080"]
Apr 02, 2015 10:36:52 AM org.apache.coyote.AbstractProtocol destroy
INFO: Destroying ProtocolHandler ["ajp-bio-8009"]


先说一下开发环境清单

Tomcat-7.0.59
xwork-core-2.2.1
struts2-core-2.2.1


分析过程
从错误情况来看,是xwork中的类com.opensymphony.xwork2.inject.ContainerImpl出现了问题。
下载xwork-core-2.2.1的源码,打开ContainerImpl文件,看到行557-583中的代码,确实存在内存未释放的问题:
//这里在线程变量中初始化了一维数组
ThreadLocal<Object[]> localContext =
  new ThreadLocal<Object[]>() {
	@Override
	protected Object[] initialValue() {
	  return new Object[1];
	}
  };

/**
* Looks up thread local context. Creates (and removes) a new context if
* necessary.
*/
<T> T callInContext(ContextualCallable<T> callable) {
	Object[] reference = localContext.get();
	if (reference[0] == null) {
	  reference[0] = new InternalContext(this);
	  try {
		return callable.call((InternalContext)reference[0]);
	  } finally {
		// Only remove the context if this call created it.
		reference[0] = null;
		//这里只将数组中的元素释放,并未将线程变量的数组对象释放
	  }
	} else {
	  // Someone else will clean up this context.
	  return callable.call((InternalContext)reference[0]);
	}
}

解决方法
问题和原因都找到,那么解决起来就简单了,有两种方案可以选择:
  1. 升级xwork的jar文件版本,根据我的检查,从xwork-core-2.3.3及以后的版本中这个问题就不存在了。相应地,你可以需要升级你的struts2-core-2.3.3以上。
  2. 修改xwork-core-2.2.1中的com.opensymphony.xwork2.inject.ContainerImpl文件,编译后放入classpath路径下(以取代jar文件中的类)
<T> T callInContext(ContextualCallable<T> callable) {
	Object[] reference = localContext.get();
	if (reference[0] == null) {
	  reference[0] = new InternalContext(this);
	  try {
		return callable.call((InternalContext)reference[0]);
	  } finally {
		// Only remove the context if this call created it.
		reference[0] = null;
		//将线程变量的数组对象释放
		this.localContext.remove();
	  }
	} else {
	  // Someone else will clean up this context.
	  return callable.call((InternalContext)reference[0]);
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值