2012-05-22 16 views
10

Tôi đang sử dụng thạch anh trong dự án của mình. ứng dụng web của tôi dường như đã gây ra rò rỉ bộ nhớ khi nó dừng lại, lỗi này là:Làm thế nào để ngăn chặn rò rỉ bộ nhớ trong thạch anh

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. 

tôi đã sử dụng org.quartz.ee.servlet.QuartzInitializerServletorg.quartz.ee.servlet.QuartzInitializerListener. Mã cho nhà máy của tôi là:

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

và cài đặt cho thạch anh trong web.xml là:

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

hãy giúp tôi để giải quyết rò rỉ bộ nhớ này !!

Trả lời

0

Tôi nghĩ rằng bạn muốn:

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

Bạn có một "thạch anh:" tiền tố mà có thể gây ra thạch anh để trở lại với giá trị mặc định của "false" cho rằng thiết lập cấu hình.

+0

không có tiền tố "thạch anh:" là chính xác. vui lòng truy cập: http: //quartz-scheduler.org/api/2.0.0/org/quartz/ee/servlet/QuartzInitializerListener.html. –

+0

Bạn đang đọc tài liệu sai: liên kết của bạn là "Trình nghe" và bạn đang định cấu hình "Servlet". Vì lý do nào đó, họ không cư xử theo cùng một cách. Xem: http://quartz-scheduler.org/api/2.0.0/org/quartz/ee/servlet/QuartzInitializerServlet.html –

+0

cài đặt này dành cho tiền tố org.quartz.ee.servlet.QuartzInitializerServlet và "quartz:" là cho org.quartz.ee.servlet.QuartzInitializerListener. Tuy nhiên, tôi xóa tiền tố "thạch anh:" nhưng không sửa lỗi rò rỉ bộ nhớ. –

2

Tôi thấy bạn khởi tạo hai trường hợp ... - đầu tiên thông qua org.quartz.ee.servlet.QuartzInitializerServlet - thứ hai thông qua org.quartz.ee.servlet.QuartzInitializerListener

Hoặc loại bỏ QuartzInitializerServlet hoặc QuartzInitializerListener (và cũng có thông số tương ứng) ... Nếu bạn muốn có nhiều phiên bản (vì lý do cụ thể), hãy đi với QuartzInitializerServlet (và đừng quên sử dụng khác nhau cho từng trường hợp)

4

Bằng cách thực hiện org.quartz.InterruptableJob bạn có thể ngắt đúng chuỗi được kích hoạt bởi dỡ hàng servlet.

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

Ví dụ này có thể gây ra lỗi điều kiện chủng tộc trên biến chủ đề, nếu công việc chưa được thực hiện trước khi nó bị gián đoạn. Tôi để giải pháp cuối cùng mở cho các đề xuất, tùy thuộc vào vòng đời của ứng dụng đích. Nếu bạn cần thực hiện đồng thời thông qua cùng một cá thể công việc, hãy tăng thêm giải pháp để xử lý nhiều luồng và xóa chú thích @DisallowConcurrentExecution.

Để làm việc này, bạn cần đặt thuộc tính thạch anh org.quartz.scheduler.interruptJobsOnShutdownWithWait thành true. Điều này có thể được thực hiện bằng cách định nghĩa một tệp thuộc tính cho trình lập lịch biểu hoặc bằng tham chiếu bean nếu sử dụng khung công tác Spring.

Ví dụ quartz.properties file:

org.quartz.scheduler.interruptJobsOnShutdownWithWait=true 

Note rằng sự gián đoạn chỉ được cử nếu lịch trình được cấu hình để chờ đợi trên tắt máy, dẫn đến một cuộc gọi đến scheduler.shutdown(true).

0

Nếu bạn đang sử dụng triển khai thực hiện giao diện ServletContextListener của riêng bạn cho ứng dụng web, bạn có thể tắt Quartz một cách duyên dáng trong phương thức contextDestroyed. Vui lòng tìm bên dưới mã mẫu cho phiên bản Quartz 2.1.7.

Công việc của bạn:

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

lên lịch công việc của bạn:

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

} 

thực hiện của bạn về giao diện 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 của bạn

<listener> 
    <listener-class>my.package.name.MyServletContextListener</listener-class> 
</listener>