Утечка памяти в веб-приложении Java при использовании ScheduledExecutorService - PullRequest
5 голосов
/ 29 марта 2012

Мой Tomcat 7 сообщает, что в моем веб-приложении может быть утечка памяти

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.

У меня в веб-приложении долго выполняется задача, которая инициализируется при запуске веб-приложения.

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, и я обнаружил, что, как только оно запущено, оно работает хорошо в течение двух дней, а затем кажется, что задачи не выполняются. В логах также нет исключений или ошибок.

Я что-то здесь не так делаю? Действительно ли существует потенциальная утечка памяти?

Ответы [ 2 ]

6 голосов
/ 29 марта 2012

вызова fScheduler.shutdownNow(); недостаточно:

Нет никаких гарантий, кроме попыток изо всех сил прекратить обработку активно выполняющихся задач.

От JavaDoc.

Вместо этого вы должны явно дождаться выполнения задач, которые в данный момент выполняются:

fScheduler.shutdownNow();
fScheduler.awaitTermination(10, TimeUnit.SECONDS);
1 голос
/ 30 марта 2012

Полагаю, вам не следует вызывать завершение работы из прослушивателя, а напрямую из сервлета.

contextDestroyed() прослушивателя слишком поздно для службы исполнителя.Как указано в javadoc Все сервлеты и фильтры будут уничтожены до . Любые ServletContextListeners уведомляются об уничтожении контекста.

, тогда как переопределение сервлетаdestroy() должно быть в порядке, как в случае с javadoc Этот метод дает сервлету возможность очищать любые ресурсы, которые хранятся (например, память, файловые дескрипторы, потоков ...

@Override
public void destroy(  ) {


     fScheduler.shutdownNow();
     fScheduler.awaitTermination(10, TimeUnit.SECONDS);

     super.destroy(  );
}
...