ClassLoaders中长期运行Tomcat进程的问题

时间:2008-11-25 17:38:55

标签: java tomcat classloader

我们已经在Tomcat 6.0.18上托管了我们的Web应用程序,并遇到了以下问题:

有两个Web应用程序WebApp1和WebApp2,它们都是相同的系统,但版本不同。

现在的问题是当tomcat运行一周或更长时间后,有时系统会给出NoClassDefFoundError!还有一些奇怪的问题,WebApp1的类加载器已经加载了WebApp2 jar中的类! WebApp1中也存在相同的jar,但版本不同。

当我们重新启动Tomcat时,一切正常!我们的JRE是1.5.10

如果您遇到此类问题,请与我们联系。

此致 Jatan Porecha

4 个答案:

答案 0 :(得分:1)

我在Tomcat中遇到过很多种类的类加载器怪异 - 即使你自己不执行任何类加载器代码,Tomcat本身也很容易产生问题。最常见的问题似乎是反复卸载和重新加载webapp泄漏类加载器并最终运行Tomcat内存不足。

我看到版本不匹配的最常见原因是Tomcat确保某些类和jar(Tomcat本身的一部分)领先于webapp类路径中的任何其他类 - commons-logging似乎是最常见的示例 - 并且可以在你不期望的时候加载,卸载或保存类加载器。

你能否提供更多细节 - 如果罐子来自第三方,那么很有可能以前有人见过这个问题。如果它是你自己的jar,那么你在应用程序中是否有自己的类加载器代码?

答案 1 :(得分:1)

我仍然没有足够的代表添加评论,所以我必须发布另一个答案。 :)

这听起来好像MailSender.class被加载到Tomcat中,而不是加载到每个单独的webapp中。 WebApp2首先加载它并且它可以工作,即使它被加载到所有Tomcat而不是WebApp2私有。当WebApp1需要该类时,它已经将其加载到Tomcat父级中,并且不会尝试将一个私有加载到WebApp1。

我首先建议你检查你的Tomcat,JRE等目录,看看是否有某种方式的jar或类的路径副本。之后,我将从两个jar文件中的每个文件中手动删除该类,然后重新启动Tomcat或Web应用程序以查看会发生什么 - 您会期望它失败并生成堆栈跟踪,这将告诉您类首次加载的位置谁试图加载它。 (例如,从类名称,您可能有一个邮件API,加载到Tomcat JVM中,将类加载到Tomcat中,而不是加载到您的webapp中)。

答案 2 :(得分:1)

您是否有特殊原因要在同一台服务器上托管完全相同代码的2个版本?

拥有2个不同的jar,名称完全相同,包含相同名称空间的类,并且具有相同的类名,似乎会导致各种问题(其中最重要的是人为错误)。

答案 3 :(得分:0)

感谢Chris的回复。

jar已经成为系统的一部分,并且有一些由其他进程共享的公共类。

让我们调用jar comutils.jar所以场景就像是,

WebApp1 (ver 1)
  |
  |- comutils.jar (ver 1)
        |
        |- MailSender.class (ver 1)


WebApp2 (ver 2)
  |
  |- comutils.jar (ver 2)
        |
        |- MailSender.class (ver 2)

此MailSender类是单身。

现在有时会发生的事情是,只要WebApp1的代码在使用getInstance方法检索其实例后调用任何MailSender方法,那么实际调用将转到MailSender(版本2)而不是版本1 !!

希望这会给你带来一些好处。