Java Quartz 内存泄漏消息

4

我在我的Web应用程序中有一个Quartz作业,由一个Servlet启动。 当我重新部署我的应用程序时,我会收到以下消息:

[DefaultQuartzScheduler_Worker-5] but has failed to stop it. This is very likely to create a memory leak

在生产环境中,我们遇到了这样一个问题:当执行 ./shutdown.sh 后,tomcat 服务器并不会停止,因此我们不得不手动杀掉进程。我认为这是由于 quartz 任务无法停止导致的。

我该如何通过重新部署应用程序或关闭服务器来停止 quartz 任务呢?

我的环境是 tomcat 7 和 quartz 2.1.6 ...

    SchedulerFactory sf = new StdSchedulerFactory();

    Scheduler scheduler = sf.getScheduler();

    scheduler.start();

    JobDetail job = JobBuilder.newJob(XYZJob.class).withIdentity("job1", "group1").build();

    Trigger trigger = TriggerBuilder.newTrigger().withIdentity("trigger1","group1")
                                                 .startNow()
                                                 .withSchedule(CronScheduleBuilder.cronSchedule("0 0 1 * * ?"))
                                                 .build();

    scheduler.scheduleJob(job, trigger);

正如您所看到的,我的工作每天只开始一次。我没有看到可以检查标志以取消工作的地方。


我认为如果这是一个专业系统,应该在serverfaultsuperuser上提问。如果你在这里没有得到任何答案,这只是一个提示。 - Qben
2个回答

4

我的解决方案是更改我的配置。我创建了一个quartz.properties文件。

org.quartz.scheduler.instanceName = XYZJob
org.quartz.threadPool.threadCount = 1
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
org.quartz.plugin.jobInitializer.class =org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin 
org.quartz.plugin.jobInitializer.fileNames = quartz-config.xml 
org.quartz.plugin.jobInitializer.failOnFileNotFound = true

一个quartz-config.xml文件。
<?xml version="1.0" encoding="UTF-8"?>

<job-scheduling-data
xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData 
http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
version="1.8">

<schedule>
    <job>
        <name>XYZJob</name>
        <group>XYZGroup</group>
        <description>Check the contracts idle period</description>
        <job-class>com.test.job.cron.XYZJob</job-class>
    </job>

    <trigger>
        <cron>
            <name>CronTriggerName</name>
            <job-name>XYZJob</job-name>
            <job-group>XYZGroup</job-group>
            <!-- It will run every day at 1 am -->
            <cron-expression>0 0 1 * * ?</cron-expression>
        </cron>
    </trigger>
</schedule>

我需要在web.xml中使用QuartzInitializerServlet。

<servlet>
     <servlet-name>QuartzInitializer</servlet-name>
     <servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
     <init-param>
         <param-name>config-file</param-name>
         <param-value>quartz.properties</param-value>
     </init-param>
     <init-param>
         <param-name>shutdown-on-unload</param-name>
         <param-value>true</param-value>
     </init-param>
     <init-param>
         <param-name>start-scheduler-on-load</param-name>
         <param-value>true</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
 </servlet>

关闭Tomcat后,我收到以下信息。
INFO: QuartzInitializer: Quartz Scheduler successful shutdown.

如果您的工作计划、工作持续时间和关闭时间不冲突,那就没问题。您的工作运行多长时间?如果系统关闭而工作仍在运行(时间更长),会发生什么? - Beryllium

3
您的工作必须定期检查(例如,在每次迭代中),是否正在进行关闭。在您的工作中正确实现此功能由您负责。Quartz和Tomcat都无法在此处提供帮助(它们如何停止线程?)。
您可以在ServletContextListener中设置标志,方法为contextDestroyed。如果设置了标志,则作业必须尽快完成。
否则,Quartz线程将在您的Web应用程序生命周期内存活!因此,Web应用程序的更新并不能保证作业被终止。我曾经遇到过僵尸作业“突然”唤醒,就在新部署之后。这是少数几种情况之一,您不相信日志文件。
这就是为什么您必须“kill” Tomcat的原因,因为存在未由Tomcat创建的运行线程。

调用没问题。有趣的软件部分是作业本身。在作业中,您应该检查“正在关闭”标志,然后作业应该终止。没有安全的方法可以从外部世界终止作业。 - Beryllium

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接