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

 更新时间:2019年10月15日 10:31:53   作者:你不知道的浪漫  
这篇文章主要介绍了Spring关闭Tomcat Servlet容器时内存泄漏问题解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

这篇文章主要介绍了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;

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

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

相关文章

  • mybatis-plus的SafetyEncryptProcessor安全加密处理示例解析

    mybatis-plus的SafetyEncryptProcessor安全加密处理示例解析

    这篇文章主要为大家介绍了mybatis-plus的SafetyEncryptProcessor安全加密处理示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • SpringMVC的概念以及快速入门示例

    SpringMVC的概念以及快速入门示例

    这篇文章主要介绍了SpringMVC的概念以及快速入门示例,SpringMVC 已经成为目前最主流的MVC框架之一,它通过一套注解,让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口,需要的朋友可以参考下
    2023-05-05
  • 关于ZooKeeper的会话机制Session解读

    关于ZooKeeper的会话机制Session解读

    这篇文章主要介绍了关于ZooKeeper的会话机制Session解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • java求最大公约数与最小公倍数的方法示例

    java求最大公约数与最小公倍数的方法示例

    这篇文章主要介绍了java求最大公约数与最小公倍数的方法,涉及java数值运算的相关操作技巧,并附带分析了eclipse环境下设置运行输入参数的相关操作技巧,需要的朋友可以参考下
    2017-11-11
  • Java SerialVersionUID作用详解

    Java SerialVersionUID作用详解

    这篇文章主要介绍了Java SerialVersionUID作用详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • spring通过构造函数注入实现方法分析

    spring通过构造函数注入实现方法分析

    这篇文章主要介绍了spring通过构造函数注入实现方法,结合实例形式分析了spring通过构造函数注入的原理、实现步骤及相关操作注意事项,需要的朋友可以参考下
    2019-10-10
  • Spring BeanFactory容器的构建和使用示例详解

    Spring BeanFactory容器的构建和使用示例详解

    BeanFactory是Spring框架中的一部分,它提供了IoC(控制反转)的实现机制,下面小编就来和大家简单聊聊BeanFactory容器的构建和使用示例吧
    2023-07-07
  • Java中Socket设置连接超时的代码分享

    Java中Socket设置连接超时的代码分享

    在我们日常连接中,如果超时时长过长的话,在开发时会影响测试,下面这篇文章主要给大家分享了关于Java中Socket设置连接超时的代码,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-06-06
  • ReentrantLock源码详解--条件锁

    ReentrantLock源码详解--条件锁

    这篇文章主要介绍了ReentrantLock源码之条件锁,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,下面我们来一起学习一下吧
    2019-06-06
  • Java如何接收前端easyui datagrid传递的数组参数

    Java如何接收前端easyui datagrid传递的数组参数

    这篇文章分享一下怎么在easyui的datagrid刷新表格时,在后端java代码中接收datagrid传递的数组参数,本文通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2023-11-11

最新评论