Tomcat关闭:contextDestroyed期间的类加载不起作用

Posted

技术标签:

【中文标题】Tomcat关闭:contextDestroyed期间的类加载不起作用【英文标题】:Tomcat shutdown: class loading during contextDestroyed does not work 【发布时间】:2014-10-20 12:53:34 【问题描述】:

我正在 Tomcat 7.0.53 中运行一个 Web 应用程序。我实现了一个 ServletContextListener(称之为 InitListener)并将其正确定义为 web.xml 中的 Listener:

  <listener>
    <description>listener that initializes common web app/service resources</description>
    <listener-class>x.y.z.InitListener</listener-class>
  </listener>

在 contextDestroyed 事件期间,我想清理一些代码(例如,使用 close () 关闭 org.jboss.netty.channel.group.ChannelGroup),但我的代码在此方法中总是失败并出现错误:

SEVERE: Exception sending context destroyed event to listener instance of class x.y.z.InitListener
java.lang.NoClassDefFoundError: org/jboss/netty/util/internal/ConcurrentHashMap$Values

现在,如果我已经在 InitListener 的 contextInitialized 部分使用了 ConcurrentHashMap$Values,例如,在 ChannelGroup 上调用 close(),那么关闭工作没有问题。

在我看来,在 contextDestroyed 事件期间,Tomcat 无法再加载该类,但如果它已预先加载,则没有问题。但这不可能是解决方案,因为我在 contextDestroyed 中使用的其他类也遇到了同样的问题。我必须预先加载我以后想使用的所有类。对我来说听起来像是一个 hack。

我做错了什么?为什么 Tomcat 在这个阶段不能再加载新的类了?

编辑:作为附加信息,仅当我对 Web 应用程序进行远程部署时才会出现此问题。当我在 Tomcat 上重新加载或取消部署 Web 应用程序时,它总是会正常关闭。就在远程部署期间,关机失败。

【问题讨论】:

有趣的问题。 Tomcat 在其自己的私有类加载器中加载每个 Web 应用程序,以便能够将 Web 应用程序类路径彼此隔离,因此它可能与此有关......但我无法解释为什么会导致这个问题。作为一种可能消除可能性的超级黑客测试,如果您将有问题的 jar 放入 tomcat/lib 而不是您的 Web 应用程序,那么问题会“消失”吗? 您是否尝试将 jar 复制到 webapp 的运行时类路径中,例如 WEB-INF/lib @Gimby 您的“超黑客测试”有效。当我将包含不可加载类(有两个)的库复制到 tomcat/lib 文件夹时,远程部署期间的问题就消失了。但正如你所说的那样,这并不是一个真正可行的生产解决方案。 @CristianGreco “复制罐子”是什么意思?去哪儿?它们都在 WEB-INF/lib 文件夹中。 不,这只是一个测试。所以它可能与Tomcat如何处理清理Web应用程序的类加载器有关......在这一点上,除了你已经找到的之外,我不知道如何继续 - 强制预加载你需要的类清理。将此问题提交给开发人员可以看到的某种形式的 Tomcat 邮件列表可能会很有趣 【参考方案1】:

我刚刚从 Tomcat 开发人员那里得到了答复。正如 Gimby 已经假设的那样,问题是由于 Tomcat 中的错误造成的。它已在 7.0.54 及更高版本中修复。

感谢您的帮助。

【讨论】:

代表修复的原始问题单:issues.apache.org/bugzilla/show_bug.cgi?id=56321

以上是关于Tomcat关闭:contextDestroyed期间的类加载不起作用的主要内容,如果未能解决你的问题,请参考以下文章

ServletContextListener接口用法

未知 sun.jdbc.odbc.JdbcOdbcDriver 的实例

java一些jar包的bug(不定期更新)

如何关闭tomcat 关闭tomcat的方法

tomcat无法关闭:8005端口为启动

tomcat 如何在命令行启动和关闭?