我的Tomcat 7报告我的webapp可能存在内存泄漏
SEVERE: The web application [/mywebapp] appears to have started a
thread named [pool-1-thread-1] but has failed to stop it. This is
very likely to create a memory leak.
我的webapp中有一个长时间运行的任务,当webapp启动时会被初始化。
public class MyContextListener implements ServletContextListener{
Scheduler scheduler = null;
public MyContextListener(){
scheduler = new Scheduler();
}
@Override
public void contextDestroyed(ServletContextEvent arg0) {
scheduler.stop();
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
scheduler.start();
}
}
..和我的Scheduler.java
public class Scheduler {
private final ScheduledExecutorService fScheduler;
public Scheduler() {
fScheduler = Executors.newScheduledThreadPool(1);
}
public void start(){
fScheduler.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
//Perform some task
}
}, 1, 240, TimeUnit.MINUTES);
}
public void stop(){
fScheduler.shutdownNow();
}
}
即使我在关闭服务器时调用scheduler.stop();
,它仍然报告可能存在内存泄漏。
此应用程序部署在jelastic.com上,我发现它一旦启动,它运行良好大约两天,然后任务似乎没有运行。日志中也没有例外或错误。
我在这里做错了吗?真的存在潜在的内存泄漏吗?
答案 0 :(得分:6)
调用fScheduler.shutdownNow();
是不够的:
除了尽力尝试停止处理主动执行任务之外,没有任何保证。
来自JavaDoc。
相反,您必须明确等待当前正在运行的任务:
fScheduler.shutdownNow();
fScheduler.awaitTermination(10, TimeUnit.SECONDS);
答案 1 :(得分:1)
我相信你不应该直接从Listener调用shutdown,而是直接从Servlet调用。
监听器的 contextDestroyed()
对于执行程序服务来说太迟了。正如javadoc 中所述,所有servlet和过滤器都将被销毁 之前,任何ServletContextListeners都会被告知上下文破坏。
而覆盖servlet destroy()
应该没问题,因为根据javadoc 这个方法为servlet提供了清理所有资源的机会(例如,内存,文件句柄, 线程 ...
@Override
public void destroy( ) {
fScheduler.shutdownNow();
fScheduler.awaitTermination(10, TimeUnit.SECONDS);
super.destroy( );
}