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

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

相关文章

  • SpringBoot整合Apache Ignite的实现

    SpringBoot整合Apache Ignite的实现

    本文主要介绍了SpringBoot整合Apache Ignite的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • Springboot项目因为kackson版本问题启动报错解决方案

    Springboot项目因为kackson版本问题启动报错解决方案

    这篇文章主要介绍了Springboot项目因为kackson版本问题启动报错解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • SpringBoot底层注解详解

    SpringBoot底层注解详解

    这篇文章主要介绍了SpringBoot底层注解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2023-05-05
  • SVN导入maven项目报错解决方案

    SVN导入maven项目报错解决方案

    这篇文章主要介绍了SVN导入maven项目报错解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • Java 数组转List的四种方式小结

    Java 数组转List的四种方式小结

    最近看了下数组转List的实现方法,总共有4种,本文就详细的介绍一下,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • SpringMVC 整合SSM框架详解

    SpringMVC 整合SSM框架详解

    这篇文章主要介绍了SpringMVC 整合SSM框架详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • MyBatisPlus超详细分析条件查询

    MyBatisPlus超详细分析条件查询

    这篇文章主要介绍了MyBatisPlus条件查询的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • 值得收藏!教你如何在IDEA中快速查看Java字节码

    值得收藏!教你如何在IDEA中快速查看Java字节码

    开发中如果我们想看JVM虚拟机怎么编译我们的Java文件,生成字节码的,用IDEA工具就可以查看,本篇文章就给大家详细介绍,对正在学习java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • Java+Swing实现医院管理系统的完整代码

    Java+Swing实现医院管理系统的完整代码

    这篇文章主要介绍了Java+Swing实现医院管理系统的完整代码,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-05-05
  • Spring实现数据库读写分离详解

    Spring实现数据库读写分离详解

    这篇文章主要介绍了Spring 实现数据库读写分离,大多数系统都是读多写少,为了降低数据库的压力,可以对主库创建多个从库,从库自动从主库同步数据,程序中将写的操作发送到主库,将读的操作发送到从库去执行,需要的朋友可以参考下
    2024-01-01

最新评论