Spring整合quartz关闭,关闭Tomcat Servlet容器时内存泄漏
2017-09-23 10:32
1881 查看
出错信息
问题分析:servlet容器关闭时发现Quartz定时器线程还在执行,对其无所适从,不懂怎么办只能强行关闭。
解决思路,在关闭容器时的contextDestroyed事件里检测ServletContext里Quartz相关属性,找到Bean然后调用它的方法结束掉。
解决方法:
关闭tomcat日志如下:
其他解决方法:Spring配置文件
笔者经过实践,发现在spring配置文件里设置参数也可以达到以上效果
22-Sep-2017 06:19:51.064 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.065 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.065 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-3] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.068 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-4] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.069 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-5] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.070 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.071 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-7] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.072 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-8] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.073 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-9] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method) org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568) 22-Sep-2017 06:19:51.080 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-10] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: java.lang.Object.wait(Native Method)
问题分析:servlet容器关闭时发现Quartz定时器线程还在执行,对其无所适从,不懂怎么办只能强行关闭。
解决思路,在关闭容器时的contextDestroyed事件里检测ServletContext里Quartz相关属性,找到Bean然后调用它的方法结束掉。
解决方法:
import java.sql.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Enumeration; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.apache.logging.log4j.web.Log4jWebSupport; import org.quartz.impl.StdScheduler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; @WebListener public class AppContextListener implements ServletContextListener { public void contextDestroyed(ServletContextEvent event) { logger.info("Destroying Context..."); try { WebApplicationContext context = (WebApplicationContext) event.getServletContext().getAttribute( WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); Enumeration<String> attributes = event.getServletContext().getAttributeNames(); while(attributes.hasMoreElements()) { String attr = attributes.nextElement(); Object prop = event.getServletContext().getAttribute(attr); logger.info("attribute.name: {},class:{}, value:{}",attr,prop.getClass().getName(),prop); } String[] beanNames = context.getBeanDefinitionNames(); for(String beanName:beanNames) { Object bean = context.getBean(beanName); logger.info("found bean attribute in ServletContext,name:{},class:{},value:{}", beanName,bean.getClass().getName(),bean); if(beanName.contains("quartz")&&beanName.contains("Scheduler")){ StdScheduler scheduler = (StdScheduler)context.getBean("org.springframework.scheduling.quartz.SchedulerFactoryBean#0"); logger.info("发现quartz定时任务"); logger.info("beanName:{},className:{}",scheduler,scheduler.getClass().getName()); if(scheduler.isStarted()) { logger.info("Quartz:waiting for job complete..."); scheduler.shutdown(true); logger.info("Quartz:all threads are complete and exited..."); } } } } catch (Exception e) { logger.error("Error Destroying Context", e); } } //https://stackoverflow.com/questions/23936162/register-shutdownhook-in-web-application public void contextInitialized(ServletContextEvent event) { //ServletContext context = event.getServletContext(); //System.setProperty("rootPath", context.getRealPath("/")); //LoggerContext ctx = (LoggerContext) LogManager.getContext(false); //ctx.reconfigure(); /*logger.info("global setting,rootPath:{}",rootPath); logger.info("deployed on architecture:{},operation System:{},version:{}", System.getProperty("os.arch"), System.getProperty("os.name"), System.getProperty("os.version")); Debugger.dump(); logger.info("app startup completed....");*/ } |
关闭tomcat日志如下:
其他解决方法:Spring配置文件
笔者经过实践,发现在spring配置文件里设置参数也可以达到以上效果
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="simpleTrigger" /> <ref bean="cronTrigger" /> <ref bean="secondCronTrigger"/> </list> </property> <property name="waitForJobsToCompleteOnShutdown" value="true"/> </bean>
<property name="waitForJobsToCompleteOnShutdown" value="true"/>可以在web关闭的时候关闭线程
相关文章推荐
- Spring整合ElasticJob 关闭Tomcat容器时内存泄漏
- 解决spring整合quartz,tomcat关闭后,quartz还在运行
- Quartz(二)整合Spring容器中bean及动态调度任务
- Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象
- quartz 与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象
- spring boot下Servlet容器Tomcat和Undertow性能对比
- Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象
- Spring3.2.11与Quartz2.2.1整合时内存泄漏问题解决
- Quartz(二)整合Spring容器中bean及动态调度任务
- Spring+Servlet整合(如何向Servlet注入属性(转),servlet获取spring容器中的bean)
- Quartz()整合Spring容器中bean及动态调度任务
- Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象
- 在使用Spring整合Quartz中,如何关闭不断输出的内容?
- springboot框架servlet容器tomcat、Jetty、undertow压测报告
- "Tomcat+Spring+Quartz"解决方案下,关闭Tomcat出现"线程未关闭,出现内存泄漏"错误
- Apache CXF实现Web Service(3)——Tomcat容器和不借助Spring的普通Servlet实现JAX-RS(RESTful) web service
- Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象
- Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象
- spring整合quartz定时器的项目中,如何关闭不断输出的batch acquisition of 0 triggers ?
- Quartz与Spring的整合-Quartz中的job如何自动注入spring容器托管的对象