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

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

相关文章

  • 在Eclipse中使用版本管理工具SVN的图文教程

    在Eclipse中使用版本管理工具SVN的图文教程

    下面小编就为大家分享一篇在Eclipse中使用版本管理工具SVN的图文教程,具有很好的参考价值,一起跟随小编过来看看吧
    2017-11-11
  • 举例讲解Java的JSON类库GSON的基本用法

    举例讲解Java的JSON类库GSON的基本用法

    GSON是谷歌在GitHub上开源的Java的JSON格式转换类库,能够实现Java对象向JSON的序列和反序列,这里我们就来举例讲解Java的JSON类库GSON的基本用法:
    2016-06-06
  • spring cloud gateway整合sentinel实现网关限流

    spring cloud gateway整合sentinel实现网关限流

    这篇文章主要介绍了spring cloud gateway整合sentinel实现网关限流,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Spring加载配置和读取多个Properties文件的讲解

    Spring加载配置和读取多个Properties文件的讲解

    今天小编就为大家分享一篇关于Spring加载配置和读取多个Properties文件的讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • Spring和SpringBoot有哪些区别

    Spring和SpringBoot有哪些区别

    相信对于用了 SpringBoot很久的同学来说,还不是很理解 SpringBoot到底和 Spring有什么区别,看完文章中的比较,或许你有了不同的答案和看法。
    2020-10-10
  • java设计模式之简单工厂模式简述

    java设计模式之简单工厂模式简述

    这篇文章主要为大家详细介绍了java设计模式之简单工厂模式,简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类的实例,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Applet小应用程序开发简介

    Applet小应用程序开发简介

    Applet小应用程序开发简介 ,用java开发的小程序,需要的朋友可以参考下
    2012-09-09
  • SpringSecurity认证流程详解

    SpringSecurity认证流程详解

    这篇文章主要介绍了SpringSecurity认证流程详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Spring Boot非Web项目运行的方法

    Spring Boot非Web项目运行的方法

    这篇文章主要给大家介绍了关于Spring Boot非Web项目运行的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • spring boot中内嵌redis的使用方法示例

    spring boot中内嵌redis的使用方法示例

    这篇文章主要给大家介绍了关于spring boot中内嵌redis使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-06-06

最新评论