【问题标题】:Spring + Quartz = Memory LeaksSpring + Quartz = 内存泄漏
【发布时间】:2014-06-24 13:11:53
【问题描述】:

我使用以下库。

  • quartz-2.2.1
  • spring-webmvc-3.2.9.RELEASE

在 Apache Tomcat/7.0.52 (Ubuntu) 上。

我使用 Spring 来配置 Quartz。

@Configuration
class QuartzConfig {
    @Bean
    FactoryBean<Scheduler> scheduler() {
        final SchedulerFactoryBean factory = new SchedulerFactoryBeanWithShutdownDelay();
        final Map<String, Object> map = new LinkedHashMap<>();
        map.put("settingsService", settingsService);
        final List<AbstractQuartzJob> jobs = new LinkedList<>();
        jobs.add(dbBackupJob());
        jobs.add(csvExportJob());
        jobs.add(csvImportJob());
        jobs.add(dbMaintenanceJob());
        jobs.add(filesystemCleanupJob());
        map.put("jobs", jobs);
        factory.setSchedulerContextAsMap(map);
        factory.setTriggers(new Trigger[] {cronTrigger});
        return factory;
    }
}

今天搜索了很多为什么调度程序任务没有正确关闭...

Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-2] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-3] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-4] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-5] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-6] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-7] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-8] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-9] but has failed to stop it. This is very likely to create a memory leak.
Jun 24, 2014 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [/feeder##1.5.0] appears to have started a thread named [scheduler_Worker-10] but has failed to stop it. This is very likely to create a memory leak.

丑陋的 hack 是编写 SchedulerFactoryBeanWithShutdownDelay 类。

public class SchedulerFactoryBeanWithShutdownDelay extends SchedulerFactoryBean {
    private static final int SHUTDOWN_TIMEOUT = 2000;

    @Override
    public void destroy() throws SchedulerException {
        log.debug("Start shutdown of Quartz scheduler factory bean");
        super.destroy();
        try {
            log.debug("wait {}ms to shutdown Quartz", SHUTDOWN_TIMEOUT);
            Thread.sleep(SHUTDOWN_TIMEOUT);
            log.debug("Quartz scheduler shutdown completed");
        } catch (InterruptedException e) {
            log.error("", e);
        }
    }
}

但是这个issue应该已经关闭了:https://jira.terracotta.org/jira/browse/QTZ-192

是我犯了错误还是可以确认?

【问题讨论】:

  • 只是出于好奇,既然 Spring 有自己的内置调度程序,为什么还要使用 quarts?
  • 为什么不呢?可能是历史原因。自从我们开始项目以来就使用它并且工作得很好,除了停止或重新启动 Web 应用程序期间出现的问题,这对我们来说不是问题。
  • 您是否真的有内存泄漏,或者您只是被日志文件中的消息带走了?另请注意,spring 默认调用scheduler.shutdown(false),因为问题提到了scheduler.shutdown(true)。要启用后者,请将SchedulerFactoryBean 上的waitForJobsToCompleteOnShutdown 属性设置为true
  • 是的,我们实际上在我们的机器上看到了内存泄漏。这就是为什么给大家的建议是在部署 Feeder web 应用程序后重新启动 tomcat。如果不经常这样做,我们会看到 perm gen space 错误,然后需要重新启动 Tomcat。谢谢你>scheduler.shutdown(true)我已经监督了这个。现在改了之后,日志里的问题就没有了……

标签: spring quartz-scheduler


【解决方案1】:

关于 Tomcat 内存泄漏的excellent article。阅读文章,启动您的 Web 应用程序,让 Quartz 作业执行,然后停止 Web 应用程序,然后获取 Tomcat 的 JVM 的堆转储,将堆转储加载到 Eclipse MAT 并找出哪些类导致内存泄漏。那么你应该能够解决这个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 2012-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多