首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tomcat中的石英调度器内存泄漏

Tomcat中的石英调度器内存泄漏
EN

Stack Overflow用户
提问于 2016-01-19 06:03:15
回答 2查看 6.4K关注 0票数 1

我使用石英版本的2.2.2和Spring版本的1.3.1。它的行为是应该的,一切都很好。但是当我试图关闭这个应用程序时,问题就出现了。日志显示有内存泄漏..。

我的石英结构;

代码语言:javascript
复制
org.quartz.scheduler.instanceName = my-app-jobs
org.quartz.scheduler.instanceId = AUTO
org.quartz.threadPool.threadCount=2
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.scheduler.skipUpdateCheck = true

我有两个类,实现以下的工作;

代码语言:javascript
复制
/**
 *
 * To Run Every 15 Minutes
 *
 */
public class MemoryDataUpdateJob implements Job {

    @Autowired
    private Dao dao;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        Logger.info(getClass().getName(), "Scheduled Memory Data Update Job Started...");

        //Read Device Settings
        dao.readDeviceSettings();

        Logger.info(getClass().getName(), "Scheduled Memory Data Update Job Finished.");
    }

}

其他班级也是相似的,做不同的事情。

调度器工厂豆如下;

代码语言:javascript
复制
@Bean
public SchedulerFactoryBean schedulerFactoryBean(
        JobFactory jobFactory,
        @Qualifier("MemoryDataUpdateJobTrigger") Trigger memoryDataUpdateJobTrigger,
        @Qualifier("MsgCountJobTrigger") Trigger msgCountJobTrigger) throws IOException {
    SchedulerFactoryBean factory = new SchedulerFactoryBean();
    factory.setJobFactory(jobFactory);
    factory.setQuartzProperties(quartzProperties());
    factory.setTriggers(memoryDataUpdateJobTrigger, msgCountJobTrigger);
    return factory;
}

我得到了像下面这样的猫日志;

代码语言:javascript
复制
19-Jan-2016 11:18:39.722 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [MyApp-1.0.0] appears to have started a thread named [schedulerFactoryBean_Worker-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)

19-Jan-2016 11:18:39.722 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [MyApp-1.0.0] appears to have started a thread named [schedulerFactoryBean_Worker-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
 java.lang.Object.wait(Native Method)

查阅了石英文档,并在属性中添加了以下内容;

代码语言:javascript
复制
org.quartz.plugin.shutdownhook.class = org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownhook.cleanShutdown = true

第一个线程消息消失了,但是关于worker-2内存泄漏的第二条消息仍然存在。

但是在我的应用程序日志中,我看到了这样的东西;

代码语言:javascript
复制
[2016-01-19 11:18:39:681] [DEBUG] [schedulerFactoryBean_Worker-1] [org.quartz.simpl.SimpleThreadPool:612] - WorkerThread is shut down.

[2016-01-19 11:18:40:047] [DEBUG] [schedulerFactoryBean_Worker-2] [org.quartz.simpl.SimpleThreadPool:612] - WorkerThread is shut down.

[2016-01-19 11:18:40:049] [INFO ] [Quartz Shutdown-Hook schedulerFactoryBean] [org.quartz.plugins.management.ShutdownHookPlugin:126] - Shutting down Quartz...

这里有什么问题?为什么会有内存泄漏,即使应用程序记录器显示线程正在关闭?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-25 12:19:19

明白了。问题是tomcat关闭了,但石英工作正在运行。如果我们等了1秒,它就会正常关闭。我们可以通过扩展SchedulerFactoryBean和重写它的destroy方法来实现它。像下面这样的东西;

代码语言:javascript
复制
public class SchedulerFactoryBeanWithWait extends SchedulerFactoryBean {

@Override
public void destroy() throws SchedulerException {
    super.destroy();
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        logError(e);
    }
 }
}

和豆子宣言;

代码语言:javascript
复制
@Bean
public SchedulerFactoryBeanWithWait schedulerFactoryBeanWithWait (
        JobFactory jobFactory,
        @Qualifier("MemoryDataUpdateJobTrigger") Trigger memoryDataUpdateJobTrigger,
        @Qualifier("MsgCountJobTrigger") Trigger msgCountJobTrigger) throws IOException {
    SchedulerFactoryBeanWithWait factory = new SchedulerFactoryBeanWithWait ();
    factory.setJobFactory(jobFactory);
    factory.setQuartzProperties(quartzProperties());
    factory.setTriggers(memoryDataUpdateJobTrigger, msgCountJobTrigger);
    return factory;
}

这使它等到线程关闭。也许这会对未来的人有所帮助。

票数 2
EN

Stack Overflow用户

发布于 2021-04-29 22:30:21

至少从Spring3.0开始,SchedulerFactoryBean就有一个标志告诉它等待作业的完成。设置标志并确保在关机时调用破坏方法:

代码语言:javascript
复制
@Bean(destroyMethodName="destroy")
public SchedulerFactoryBean schedulerFactoryBean(
        JobFactory jobFactory,
        @Qualifier("MemoryDataUpdateJobTrigger") Trigger memoryDataUpdateJobTrigger,
        @Qualifier("MsgCountJobTrigger") Trigger msgCountJobTrigger) throws IOException {
    SchedulerFactoryBean factory = new SchedulerFactoryBean();
    factory.setWaitForJobsToCompleteOnShutdown(true);
    factory.setJobFactory(jobFactory);
    factory.setQuartzProperties(quartzProperties());
    factory.setTriggers(memoryDataUpdateJobTrigger, msgCountJobTrigger);
    return factory;
}

或者使用XML配置:

代码语言:javascript
复制
<bean id="scheduler"
        class="org.springframework.scheduling.quartz.SchedulerFactoryBean"
        destroy-method="destroy">
    <property name="waitForJobsToCompleteOnShutdown" value="true" />
    ....
</bean>

请参阅:https://docs.spring.io/spring-framework/docs/3.0.0.RELEASE/javadoc-api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html#setWaitForJobsToCompleteOnShutdown(boolean)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34869562

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档