首页 > 编程 > Java > 正文

Spring关闭Tomcat Servlet容器时内存泄漏问题解决方案

2019-11-26 08:29:05
字体:
来源:转载
供稿:网友

这篇文章主要介绍了Spring关闭Tomcat Servlet容器时内存泄漏问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

出错信息

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)

问题分析

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;@WebListenerpublic 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关闭的时候关闭线程

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表