【问题标题】:Close connections in pool/cache (cache created with singleton) when Eclipse reloads context当 Eclipse 重新加载上下文时,关闭池/缓存中的连接(使用单例创建的缓存)
【发布时间】:2010-09-27 14:23:33
【问题描述】:

我正在使用 Eclipse 开发一个 java web 应用程序,我的 IT 部门打电话说我有超过 75 个开放的 oracle 连接到来自我的 PC 的开发 Oracle 服务器。部署的应用程序已经使用同一个单例连接 bean 一年了,我没有遇到任何超出连接的问题。 IT 甚至确认我在部署服务器上只有 4 个打开的连接。当我在 Eclipse 中进行本地开发时,发生了一些事情。

查看控制台调试输出,初始启动时一切正常

Sep 27, 2010 9:39:08 AM org.apache.catalina.startup.Catalina start
== no ConnCache Bean instance found 
== Initializing Connection Cache Data Src
== About to load the properties
== Initializing Datasource for using jdbc:oracle:thin:@hostname:port:oracle-sid
== Reading property file 
== Setting InitialLimit to 3
== Properties {TimeToLiveTimeout=4, MinLimit=4, ConnectionWaitTimeout=44, MaxLimit=5, InitialLimit=3, AbandonedConnectionTimeout=281, InactivityTimeout=269}

但是当 Eclipse 重新加载上下文时,我在控制台中注意到以下 SEVERE 消息

Sep 27, 2010 9:40:38 AM org.apache.catalina.core.StandardContext reload
INFO: Reloading this Context has started
Sep 27, 2010 9:40:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesJdbc
SEVERE: The web application [] registered the JBDC driver [oracle.jdbc.driver.OracleDriver] but failed to unregister 
it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
Sep 27, 2010 9:40:38 AM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: The web application [] appears to have started a thread named [Thread-9] but has failed to stop it. 
This is very likely to create a memory leak.

我猜测 Eclipse 每次重新加载上下文时都会重新创建连接缓存,并且旧的连接和缓存不会被破坏。重新加载上下文时,如何让 Eclipse 终止缓存或关闭所有先前的连接。如有必要,我可以发布我的 connectionBean 类。

【问题讨论】:

  • 勇敢的人!在生产服务器上开发。编辑,对不起,这不是那么有帮助。在我的正常设置(eclipse、tomcat)中,我运行了一个本地版本的 tomcat,它可以重新启动,从而刷新连接池。我不知道这在您的设置中是否可行。
  • @Jaydee,我正在本地开发。我们有一个开发、阶段和生产 Web 服务器以及一个开发、阶段和生产 Oracle 服务器。 Eclipse IDE 上的本地开发使用本地 apache 安装,但连接到 Dev Oracle 服务器。部署的应用程序位于生产网络服务器上,并连接到生产 Oracle 服务器。
  • 对不起,我假设了很多,并且不合时宜。 Vineet 的回答看起来值得一试。
  • 不用担心,我编辑了我的帖子以澄清它是针对开发 oracle 服务器的。真的没有理由在我的 PC 上拥有 db 的第 4 个副本。

标签: java eclipse connection


【解决方案1】:

您似乎是通过以前版本的应用程序的未关闭连接泄漏内存。如果您选择将 Web 应用程序从 Eclipse 自动发布到 Tomcat,这是很有可能的。

Tomcat 在尝试执行重新加载时会丢弃 Web 应用程序的当前类加载器。来自此 GC 根(类加载器)的所有对象,仍将被持有,不会被垃圾收集。由于单例的存在(我假设单例存储DataSource 对象或维护Connection 对象池),这些Connection 对象永远不会被视为无法访问的对象,因此,将没有资格获得 GC。

在短期内,您可以做到以下几点:

  • 如果您能提供帮助,请在需要发布应用程序的新版本时重新启动 Tomcat。
  • 实现ServletContextListener,并在servlet(应用程序)上下文被破坏时尝试丢弃单例引用。这使得单例对象无法访问,因此符合 GC 条件。建议这样做,因为在生产环境中必然会发生同样的情况,除非重新启动 Tomcat。

顺便说一句,只要在不重新启动服务器的情况下一次又一次地重新部署应用程序,这种行为在单例中会导致内存并因此在任何应用程序服务器中发生连接泄漏。防止这种情况的唯一方法是确保在销毁应用程序上下文时销毁单例。

【讨论】:

  • 我正在处理数据的副本。我们有 3 台 Oracle 服务器,开发/阶段/生产,我正在从我的 PC 连接到开发 Oracle 服务器,完全可以接受 - 我正在使用开发 Oracle 服务器。感谢 SevlertConecttextListener 方法。我会调查的。
  • @jeff,好吧,那条评论毫无意义,所以我删除了它。在调试会话期间,我被数据库重新启动所困扰,但这并不适用于你。
  • 我尝试了 SevlertConecttextListener 但方法 contextDestroyed 不会在重新加载时调用,只有当我关闭 Tomcat 时。当我停止 Tomcat 并且 contextDestroyed 方法尝试丢弃单例时,单例不再存在(如预期的那样),因此侦听器并没有真正为目的服务。除非有任何其他建议,否则我可能只是更改 server.xml 中的 reload=false 并按照您的建议手动重新启动服务器。
  • @jeff,嗯,我没想到。您可以尝试在 servlet 的销毁事件中取消单例(如果您有控制器,可能是控制器),但在您进行此尝试后,我不太确定。
猜你喜欢
  • 2014-02-06
  • 1970-01-01
  • 1970-01-01
  • 2013-03-02
  • 2020-05-27
  • 2014-05-21
  • 1970-01-01
  • 2011-12-15
  • 2012-09-21
相关资源
最近更新 更多