2012-05-22 3 views
10

내 프로젝트에서 석영을 사용하고 있습니다. 멈출 때 내 웹 응용 프로그램이 분명히 메모리 누수가 발생했습니다 오류는 다음과 같습니다 석영의 메모리 누출을 방지하는 방법

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을 사용했다. 내 공장에 대한 코드는 다음과 같습니다 web.xml에

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

및 설정 석영은 다음과 같습니다

<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> 

날이 메모리 누수를 해결하기 위해 도와주세요!

답변

0

난 당신이 원하는 생각 : 접두사 석영가 구성 설정에 대해 "false"를 기본값으로 되돌릴의 원인이 될 수 있습니다 : 당신은 "석영"가

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

. 첫째 org.quartz.ee.servlet.QuartzInitializerServlet 을 통해 - -

+0

아니요, "quartz :"접두사가 정확합니다. http : //quartz-scheduler.org/api/2.0.0/org/quartz/ee/servlet/QuartzInitializerListener.html을 방문하십시오. –

+0

잘못된 문서를 읽고 있습니다 : 링크가 "Listener"이고 "Servlet"을 구성하고 있습니다. 웬일인지, 그들은 같은 방법으로 행동하지 않는다. 참조 : http://quartz-scheduler.org/api/2.0.0/org/quartz/ee/servlet/QuartzInitializerServlet.html –

+0

이 설정은 org.quartz.ee.servlet.QuartzInitializerServlet 용이며 "quartz :"접두어는입니다. org.quartz.ee.servlet.QuartzInitializerListener. 그러나, 나는 "석영 :"접두사를 삭제하지만 정확한 메모리 누출은 아닙니다. –

2

난 당신이 두 개의 인스턴스 ... 를 초기화 참조 org.quartz.ee.servlet.QuartzInitializerListener

을 통해 두 번째

을 하나 제거 QuartzInitializerServlet 또는 QuartzInitializerListener (및 당신은 당신이 제대로 트리거 스레드를 중단 할 수 org.quartz.InterruptableJob을 구현함으로써)

4

을 QuartzInitializerServlet과 함께 할 것입니다 (그리고 인스턴스 당 다른 사용하는 것을 잊지 마세요() 특정 이유로 여러 인스턴스를 갖고 싶어하는 경우도 ... ) 매개 변수를 해당 서블릿 언로드. 가 중단되기 전에 작업이 실행되지 않은 경우

@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으로 설정해야합니다. 이것은 스케줄러에 대한 프로퍼티 파일을 정의하거나 스프링 프레임 워크를 사용한다면 빈 참조에 의해 정의 될 수 있습니다.

quartz.properties 파일 : 스케줄러가 scheduler.shutdown(true)에 대한 호출의 결과로, 종료에 대기하도록 구성된 경우 중단 만 전달되는 것을

org.quartz.scheduler.interruptJobsOnShutdownWithWait=true 

.

0

웹 애플리케이션을위한 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 CronJobTrigger 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> 
관련 문제