Resolving the problem of memory leak when integrating Spring3.2.11 and Quartz2.2.1

Source: Internet
Author: User

Quartz is an open-source framework for scheduled task scheduling, which is convenient to use. and spring's support package is integrated with quartz. However, I encountered the problem of memory leak in the process of using the Web application.

The problem arises

The author uses Spring+quartz as follows (familiar with Spring+quartz can skip the direct look at the problem):

1. Configuring the Scheduler Factory

<id= "Schedulerfactory"  class= " Org.springframework.scheduling.quartz.SchedulerFactoryBean "></Bean  >

2. Write the implementation class Quartzjob for the job to perform the task

 //  This is where spring's Quartzjobbean  is to be inherited. Span style= "color: #0000ff;" >public  class  quartzjob extends  Span style= "color: #000000;"     > Quartzjobbean { /**   * task execution content.  */  @Override  protected  void  executeinternal (jobexecutioncontext context) throws   Jobexecutionexception { //
      

3. Inject scheduler from the Scheduler factory into the business logic class. Note here that the injected is actually a scheduler instance produced by Schedulerfactory ( people who are unfamiliar with spring will naturally think that injecting is an instance of Schedulerfactory, This is because spring's Schedulerfactorybean implements the Factorybean interface, so the result of the injection is factorybean.getobject () An example of the obtained, off-topic).

  <BeanID= "Taskservice"class= "Com.xxxx.xx.service.impl.TaskServiceImpl"Init-method= "Init"Scope= "Singleton">    < Propertyname= "Scheduler">      <refBean= "Schedulerfactory"/>    </ Property>  </Bean>
 Public class Taskserviceimpl {    private  Scheduler Scheduler; /**      * Injected by spring through the factory, this instance is a singleton.      @param Scheduler      */     Public void Setscheduler (Scheduler Scheduler) {        this. Scheduler = Scheduler;    } 

4. In the Business logic class Taskserviceimpl, use Scheduler to perform the task. This allows you to dynamically add, delete, restart, and so on tasks. Another important feature is the ability to dynamically change cron expressions to change the timing rules of a task.

1     /**2 * Added Tasks. 3      * @paramJobName4      * @paramJobgroup5      * @paramCron6      */7      Public voidaddjob (String jobName, String jobgroup, String cron, String kindid) {8         Try {9             if(Stringutil.isempty (jobName) | | Stringutil.isempty (jobgroup) | |Stringutil.isempty (cron)) {Ten                 Throw NewBusinessexception ("Timed task creation failed with null parameter"); One             } AJobdetail Jobdetail = Jobbuilder.newjob (quartzjob.class). Withidentity (JobName, Jobgroup). Build (); -Jobdetail.getjobdatamap (). Put ("Jobkind", Kindid); -             //Expression Scheduler Builder theCronschedulebuilder Schedulebuilder =Cronschedulebuilder.cronschedule (cron); -             //build a new trigger according to the new cronexpression expression -Crontrigger trigger =Triggerbuilder.newtrigger (). Withidentity (JobName, Jobgroup). Withschedule (Schedulebuilder). build (); - scheduler.schedulejob (Jobdetail, trigger); +Log.info ("New timed task, Name:" + JobName + ", Group:" + Jobgroup + ", cron:" +cron); -}Catch(schedulerexception e) { +             //Handling of exceptions A         } at}

Note that the scheduler of line 18 is injected by spring.

This usage is not problematic during use, but the following critical warning is Chuxian when the Web app is hot-deployed in Tomcat6, and if this warning is ignored, it causes Tomcat PermGen space OOM after frequent reload.

June, 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearreferencesthreadssevere:the Web Application [ /feeder# #1.5.0] appears to had started a thread named [Scheduler_worker-1] but had failed to stop it. This was very likely to create a memory leak. June, 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearreferencesthreadssevere:the Web Application [ /feeder# #1.5.0] appears to had started a thread named [Scheduler_worker-2] but had failed to stop it. This was very likely to create a memory leak. June, 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearreferencesthreadssevere:the Web Application [ /feeder# #1.5.0] appears to had started a thread named [scheduler_worker-3] but had failed to stop it. This was very likely to create a memory leak. June, 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearreferencesthreadssevere:the Web Application [ /feeder# #1.5.0] appears to has started a thread named [scheduler_worker-4] but Have failed to stop it. This was very likely to create a memory leak. June, 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearreferencesthreadssevere:the Web Application [ /feeder# #1.5.0] appears to had started a thread named [Scheduler_worker-5] but had failed to stop it. This was very likely to create a memory leak. June, 5:14:38 AM org.apache.catalina.loader.WebappClassLoader clearreferencesthreadssevere:the Web Application [ /feeder# #1.5.0] appears to had started a thread named [scheduler_worker-6] but had failed to stop it. This was very likely to create a memory leak. June, 5:14:38 AM Org.apache.catalina.loader.WebappClassLoader clearreferencesthreads
The cause of the problem

The reason is that the open Scheduler_worker thread is not closed. However, Spring's Schedulerfactorybean implements the Disposablebean interface, which means that the Web container executes destroy () when it is closed, and executes as follows:

    /**      * Shut down the Quartz Scheduler on Beans factory shutdown,     * stopping all scheduled jobs.      */     Public void throws schedulerexception {        logger.info ("shutting down Quartz Scheduler");         this. Scheduler.shutdown (this. waitforjobstocompleteonshutdown);    }

Indicates that the factory has done shutdown. So, the problem arises in the real execution of the Scheduler.shutdown (true).

It turns out that this is a quartz bug (see https://jira.terracotta.org/jira/browse/QTZ-192), after calling Scheduler.shutdown (true), Quartz checks that the thread does not wait for those worker threads to stop and ends.

Online says that the bug has been patched in the Quartz2.1 version, but I still have a problem with the 2.2.1 version.

Solution to the problem

So how to solve the problem, here is a less beautiful scenario: After calling Scheduler.shutdown (true), add a little sleep time, waiting for the worker thread to stop all. As follows:

1. The custom schedulerfactory inherits Spring's Schedulerfactorybean, overwriting destroy () to increase the delay.

 Public classSchedulerfactorybeanwithshutdowndelayextendsSchedulerfactorybean {/*** A less attractive solution to quartz memory leaks: * Increase the delay after calling Scheduler.shutdown (true), waiting for the worker thread to end. */@Override Public voidDestroy ()throwsschedulerexception {Super. Destroy (); Try{Thread.Sleep (1000); } Catch(interruptedexception e) {Throw NewRuntimeException (e); }    }}

2. Replace the Schedulerfactorybean in the spring configuration file with the custom factory.

<id= "Schedulerfactory"  class= " Com.sinosoft.ms.task.SchedulerFactoryBeanWithShutdownDelay "></Bean  >

OK, problem solved.

Resolving the problem of memory leak when integrating Spring3.2.11 and Quartz2.2.1

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.