为啥 Spring Context 没有优雅地关闭?

Posted

技术标签:

【中文标题】为啥 Spring Context 没有优雅地关闭?【英文标题】:Why Spring Context not gracefully closed?为什么 Spring Context 没有优雅地关闭? 【发布时间】:2013-05-04 02:02:30 【问题描述】:

在基于Spring framework 3.0.5 的Web 应用程序的stopundeploy/redeploy 上,在Tomcat7's catalina.out 中记录了以下错误:

SEVERE: The web application [/nomination##1.0-qa] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@4f43af8f]) and a value of type [org.springframework.security.core.context.SecurityContextImpl] (value [org.springframework.security.core.context.SecurityContextImpl@ffffffff: Null authentication]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.

我最初想在那里实现 ServletContextListenerclose() 上下文。但是,发现实现ServletContextListenerContextLoaderListenerweb.xml中是这样设置的:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

来自 Javadocs:

**contextDestroyed**

public void contextDestroyed(ServletContextEvent event)
Close the root web application context.
Specified by:
contextDestroyed in interface ServletContextListener

那么,我的问题是为什么 ContextLoaderListener.contextDestroyed() 没有完全释放 ThreadLocal?

我们遇到了PermGen 错误,并在调查时发现了这一点。有几个地方有类似下面的代码:

ApplicationContext context = WebApplicationContextUtils
            .getWebApplicationContext(se.getSession().getServletContext());

MyBeanClass x = context.getBean(
            "myBean", MyBeanClass.class);
x.someMethod(); 

我想知道上面的 sn-p 是否正在停止干净关机? 任何指针将不胜感激。

【问题讨论】:

在将根应用程序上下文一分为二时,我开始遇到此错误。我现在有一个用于引导程序的根上下文(具有相同的两个子 servlet 上下文),而不是具有两个子 servlet 上下文的单个根上下文,并且稍后我以编程方式创建了一个子上下文。在此设计中,安全配置继续保留在根应用程序上下文中,但现在出现了泄漏警告。显然,在我的情况下,这与将根应用程序上下文一分为二有关。 @Mihai Danila 我只有一个应用程序上下文。 您的安全上下文设置如何? 您取消注册驱动程序了吗? @Override public void contextDestroyed(ServletContextEvent arg0) Enumeration drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) Driver driver = drivers.nextElement();尝试 DriverManager.deregisterDriver(driver); 捕捉 (SQLException e) @MihaiDanila 我知道有点晚了,但你能分享你的应用程序 ctx 吗?谢谢。 【参考方案1】:

hotdeploy 有很多你应该关心的问题:

1-注销数据库驱动程序see here。

2-关闭多任务应用程序中的任务:您可以在开发模式下将重启延迟将近 1 小时。

3-Kill context of spring:你在上面做了,但注意不要从 XML 中导入 XML。

4-Kill JVM 内存中存在的缓存对象:制作小对象,你在初始化吗 构造函数中的bean?将其更改为 none 构造函数以保持在方法范围内杀死它们! 类中调用bean的方法有多少?如果许多方法调用 bean 在从作用域中出来后不期望 java 杀死对象,jvm 会保留它以提高性能..,所以保持你的类小!。

你的代码怎么样?您是否在循环中声明变量?使用后你是=null列表还是对象?

5-你可以增加tomcat的启动时间和停止时间。

还可以将 rebel 或 springboot 项目视为助手。

【讨论】:

以上是关于为啥 Spring Context 没有优雅地关闭?的主要内容,如果未能解决你的问题,请参考以下文章

从 Shell 脚本优雅地关闭 Spring Boot 应用程序

为啥不尝试 I/O 就不可能检测到 TCP 套接字已被对等方优雅地关闭?

如何通过start-stop-daemon优雅地关闭Spring Boot应用程序[重复]

Spring 优雅关闭 - 不支持请求方法发布

spring-boot 2 优雅关闭网络

Spring Boot Maven 插件 - spring-boot:run 和优雅关闭