我有一个Web应用程序(使用Spring3.1),它使用@调度注释来定期执行工作任务(调度延迟)。工作任务打开与AWSDynamoDb的连接,并执行一些DB读取/更新。当我停止webapp(来自Tomcat管理器)时,我在catalina. out中收到此消息:
"SEVERE:Web应用程序[]似乎已经启动了一个名为[java-sdk-超文本传输协议-连接-收割机]的线程,但未能阻止它。这很可能会造成内存泄漏。"
我有一种感觉,这与我的计划任务在Tomcat停止后仍在运行有关。
@Service
public class TaskScheduler implements ApplicationListener<ContextClosedEvent>{
@Autowired
private WorkerTask workerTask;
AmazonDynamoDBClient myDbConn = null;
private TaskScheduler() {
myDbConn = new AWSConnector("aws.properties").getDynamoConnection();
}
/*
* Will be repeatedly called, 10 seconds after the finish of the previous
* invocation.
*/
@Scheduled(fixedDelay=100000)
public void process() {
System.out.println("Scheduling worker task");
//worker task does some db read/writes
Future<String> status = workerTask.work(myDbConn);
if (status.isDone()) {
System.out.println("Completed Task");
return;
}
}
@Override
public void onApplicationEvent(ContextClosedEvent arg0) {
if(event instanceof ContextClosedEvent) {
// TODO Auto-generated method stub
if(myDbConn != null) {
this.myDbConn.shutdown();
}
}
}
调度程序-ser v let. xml:
<task:annotation-driven scheduler="taskScheduler"/>
<task:scheduler id="taskScheduler" pool-size="2"/>
......
<bean id="TaskScheduler" class="com.sample.TaskScheduler"/>
我这样做正确吗?a)我没有显式启动TaskScheduler。所以我假设Spring负责启动此服务。调用'this. myDbConn.Shutdown()'。尽管如此,我还是得到了错误。我正在使用SpringMVC。
这可能是由AWS库引起的,它在后台启动了一个名为com. amazonaws.http.IdleConnectionReaper的线程
您可以通过实现ServletContextListener来关闭它以在关闭时关闭它
public class YourListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent contextEvent) {
}
@Override
public void contextDestroyed(ServletContextEvent contextEvent) {
try {
com.amazonaws.http.IdleConnectionReaper.shutdown();
} catch (Throwable t) {
// log the error
}
}
}
并将其添加到您的web. xml
<listener>
<listener-class>
your.package.YourListener
</listener-class>
</listener>
我也有这个问题,但我决定了上面@David_Wartell的替代解决方案。
我从Amazon的aws-java-sdk库中找到了一个类,该类正在创建一个有问题的对象/对象,这些对象正在启动IdleConnectionReaper线程,但从未关闭(这些com.amazonaws.services. ec2.Amazon EC2Client和com.amazonaws.services.cloud dwatch.Amazon CloudWatchClient)。然后我在这个类中添加了一个销毁()方法,该方法称为静态方法com.amazonaws.http.IdleConnectionReail.Shutdown()。当类被垃圾回收时调用销毁方法,并使用Spring application ationContext.xml进行配置。这样做的优点是它甚至可以用于非Web应用程序,并且它将线程关闭与您的Web上下文分离。正确的解决方案是启动IdleConnectionReaper线程的amazon aws-java-sdk库中的类应该关闭它,但它们没有-因此bug。有关我的解决方案,请参阅下面的参考和代码片段:
应用上下文. xml
<bean id="YourBeanName" class="com.your.package.name.YourBeanName" destroy-method="destroy">
<!-- other optional configuration goes here -->
</bean>
YourBeanName.java-(创建冒犯亚马逊对象的类)
public class YourBeanName {
// omitted code
public void destroy() {
com.amazonaws.http.IdleConnectionReaper.shutdown();
}
// omitted code
}
参考文献:
Amazon论坛-关闭IdleConnectionReaper
Spring文档-自定义bean的性质
除了Stuart的回答之外(假设你使用的是Spring),如果你不使用XML配置文件,还有一个选择:
@Component
public class MyBean {
// ...
@PreDestroy
private void cleanUp() {
try {
// Shutting down AWS IdleConnectionReaper thread...
com.amazonaws.http.IdleConnectionReaper.shutdown();
} catch (Throwable t) {
// log error
}
}
}
当我使用bean实现com.amazonaws.services. s3.Amazon S3接口时,它对我很有效。