我在tomcat 5.5和tomcat 6.0服务器上遇到了这个奇怪的问题。我有两个要安装在tomcat上的Web应用程序。启动tomcat时,这两个Web应用程序也同时启动,但是有时一个Web应用程序由于一个应用程序的初始化失败而无法初始化,而另一个应用程序在运行时却收到classnotfoundexception错误。在tomcat 7.0中,即使另一个应用程序未能初始化,该应用程序也可以正常运行。
经过一些调试后,我知道有一个名为crystal.jar的jar,位于两个应用程序的web-inf / lib文件夹中。我将jar移到tomcat的common / lib文件夹中,然后它开始正常工作。我想知道为什么它在tomcat 7.0中不能正常工作,而不是在tomcat 5.x和tomcat 6.x版本中。这些版本之间的类加载体系结构是否有变化?
谢谢
编辑1: 该库位于两个应用程序WEB-INF \ lib目录的位置,并且它们与外部DLLS没有依赖关系。刚刚,我阅读了有关tomcat 5.5类加载器的体系结构,并了解到每个Web应用程序都有自己的类加载器。WEB-INF \ lib文件夹和classes文件夹中的库将被加载到该类加载器中。无论存储在公共目录下的哪个库,都将放入共享的类加载器中。然后,应将此库分别加载到Web应用程序的单独的类加载器中。即使一个Web应用程序无法启动,其他Web应用程序也应独立运行。这就是为什么我感到奇怪并需要调查进一步的原因。
终于找到了这个问题的答案
当系统类引用一个库类,并且存在的时间超过其寿命时,就会存在一种已知的PermGen内存泄漏。一个示例是Java发现JDBC驱动程序或其他服务并“自动注册”它时。它一直在系统中对其进行引用,但是该类本身属于Web应用程序,必须在应用程序停止时将其卸载- 但由于该引用而不能卸载。并非所有此类参考都易于清除。
这种情况下的一个典型症状是,依赖于该系统功能的第一个Web应用程序将成功,但是依赖于该系统功能的第一个Web应用程序将失败(因为系统中注册的服务属于第一个Web应用程序,并且无法从第二个应用程序的类加载器,反之亦然)。
Tomcat 7和最新版本的Tomcat 6在其默认配置中可以更好地防止某些已知的PermGen内存泄漏。
Tomcat 5.5根本没有这种保护。
编辑 一些参考
http://people.apache.org/~markt/presentations/2010-08-05-Memory-Leaks- JavaOne-60mins.pdf http://people.apache.org/~markt/presentations/2010-11-04 -Memory- Leaks-60mins.pdf
http://eclipse.org/mat/
http://wiki.apache.org/tomcat/FAQ/ 疑难解答和诊断http://wiki.apache.org/tomcat/MemoryLeakProtection