12

プロジェクトでクォーツを使用しています。私の Web アプリケーションは、停止時にメモリ リークを引き起こしたようです。エラーは次のとおりです。

SEVERE: A web application appears to have started a TimerThread named [Timer-12] via the java.util.Timer API but has failed to stop it. To prevent a memory leak, the timer (and hence the associated thread) has been forcibly cancelled. 
Jan 2, 2013 6:55:35 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [DefaultQuartzScheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak.

と を使用org.quartz.ee.servlet.QuartzInitializerServletorg.quartz.ee.servlet.QuartzInitializerListenerました。私の工場のコードは次のとおりです。

StdSchedulerFactory factory = (StdSchedulerFactory) context.getAttribute(QuartzInitializerListener.QUARTZ_FACTORY_KEY );

web.xml のクォーツの設定は次のとおりです。

<servlet>
         <servlet-name>
             QuartzInitializer
         </servlet-name>
         <display-name>
             Quartz Initializer Servlet
         </display-name>
         <servlet-class>
             org.quartz.ee.servlet.QuartzInitializerServlet
         </servlet-class>
         <load-on-startup>
             1
         </load-on-startup>
         <init-param>
             <param-name>shutdown-on-unload</param-name>
             <param-value>true</param-value>
         </init-param>
         <init-param>
             <param-name>wait-on-shutdown</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>
     </servlet>
     <context-param>
         <param-name>quartz:shutdown-on-unload</param-name>
         <param-value>true</param-value>
     </context-param>
     <context-param>
         <param-name>quartz:wait-on-shutdown</param-name>
         <param-value>true</param-value>
     </context-param>
     <context-param>
         <param-name>quartz:start-on-load</param-name>
         <param-value>true</param-value>
     </context-param>
     <listener>
         <listener-class>
             org.quartz.ee.servlet.QuartzInitializerListener
         </listener-class>
     </listener>

このメモリリークを解決するのを手伝ってください!!

4

4 に答える 4

4

実装org.quartz.InterruptableJobすることで、サーブレットのアンロードによってトリガーされたスレッドを適切に中断できます。

@DisallowConcurrentExecution
public class Job implements InterruptableJob {

    private Thread thread;

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        thread = Thread.currentThread();
        // ... do work
    }

    @Override
    public void interrupt() throws UnableToInterruptJobException {
        thread.interrupt();
        try {
            thread.join();
        } catch (InterruptedException e) {
            throw new UnableToInterruptJobException(e);
        } finally {
            // ... do cleanup
        }
    }
}

この例では、ジョブが中断される前に実行されていない場合、スレッド変数で競合状態のバグが発生する可能性があります。ターゲット アプリケーションのライフ サイクルに応じて、提案のために最終的なソリューションを開いたままにします。同じジョブ インスタンスを介した同時実行が必要な場合は、ソリューションを拡張して複数のスレッドを処理し、@DisallowConcurrentExecution注釈を削除します。

これを機能させるには、クォーツ プロパティorg.quartz.scheduler.interruptJobsOnShutdownWithWaitを に設定する必要がありますtrue。これは、スケジューラのプロパティ ファイルを定義するか、Spring フレームワークを使用している場合は Bean 参照によって行うことができます。

サンプルquartz.propertiesファイル:

org.quartz.scheduler.interruptJobsOnShutdownWithWait=true

スケジューラがシャットダウン時に待機するように構成されている場合にのみ割り込みがディスパッチされ、結果として が呼び出されることに注意scheduler.shutdown(true)してください。

于 2013-03-07T11:25:22.310 に答える
2

2 つのインスタンスを初期化しているのがわかります... - 最初は org.quartz.ee.servlet.QuartzInitializerServlet を介して - 2 番目は org.quartz.ee.servlet.QuartzInitializerListener を介して

QuartzInitializerServlet または QuartzInitializerListener (および対応するパラメーター) を削除します... (特定の理由で) 複数のインスタンスが必要な場合は、QuartzInitializerServlet を使用します (インスタンスごとに異なるものを使用することを忘れないでください)。

于 2012-09-24T11:48:03.807 に答える
1

Web アプリケーションに ServletContextListener インターフェースの独自の実装を使用している場合は、contextDestroyed メソッドで Quartz を正常にシャットダウンできます。Quartz バージョン 2.1.7 のサンプル コードを以下に示します。

あなたの仕事:

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class CronJob implements Job {
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        // TODO: do you job
    }
}

ジョブ スケジューラ:

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;

public class CronJobScheduler {

    private static CronJobScheduler instance = new CronJobScheduler();  
    private Scheduler scheduler;

    private CronJobScheduler() {    
        try {
            scheduler = new StdSchedulerFactory().getScheduler();
        } catch (SchedulerException e) {
            // TODO
        }
    }

    public static CronJobScheduler getInstance() {
        return instance;
    }

    public void trigger() {
        JobKey jobKey = JobKey.jobKey("myJobName", "myJobGroup");       
        JobDetail job = JobBuilder.newJob(CronJob.class).withIdentity(jobKey).build();

        Trigger trigger = TriggerBuilder
                .newTrigger()
                .withIdentity("myTriggerName", "myJobGroup")
                .withSchedule(CronScheduleBuilder.cronSchedule("0 0 1,13 * * ?"))
                .build();

        try {
            scheduler.start();
            scheduler.scheduleJob(job, trigger);
        } catch (SchedulerException e) {    
            // TODO
        }
    }

    public void shutdown(boolean waitForJobsToComplete) {
        try {
            scheduler.shutdown(waitForJobsToComplete);
        } catch (SchedulerException e) {
            // TODO
        }
    }

}

ServletContextListener インターフェースの実装:

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        CronJobScheduler.getInstance().shutdown(true);
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        CronJobScheduler.getInstance().trigger();
    }

}

あなたの web.xml

<listener>
    <listener-class>my.package.name.MyServletContextListener</listener-class>
</listener>
于 2016-05-06T11:01:49.503 に答える
0

私はあなたが欲しいと思います:

     <init-param>
         <param-name>wait-on-shutdown</param-name>
         <param-value>true</param-value>
     </init-param>

「quartz:」プレフィックスがあり、Quartzがその構成設定のデフォルト値「false」に戻る可能性があります。

于 2012-05-22T15:50:10.557 に答える