Tomcat是否将两个相同的库文件加载到内存中,如果它们位于两个Web应用程序中?
我有两个应用程序在tomcat/webapps
文件夹下。
tomcat/webapps/App1 tomcat/webapps/App2
这两个应用程序共享相同的库。 它们存储在例如tomcat/webapps/App1/WEB-INF/lib
。
这两个库在内存中加载两次?
我应该把这些共享库放在tomcat/server/lib
吗?
正如您在这里看到的,Tomcat在您的服务器上为每个webapp创build一个类加载器。 因此,如果你有共享同一个库的webapp1和webapp2,那么这个库确实会被加载两次。
如果Tomcat服务器上运行的所有 Web应用程序共享此库,则最终可以将此库放置在公共目录(tomcat-dir / common / lib)中。
我不build议将jar文件放在共享文件夹中。 比方说,您将来需要部署第三方应用程序,该应用程序在WEB-INF文件夹中具有较新版本的jar文件。 对于这个应用程序,jar的类将被加载两次(即使它们具有相同的名称),一个来自共享文件夹,一个来自web应用程序文件夹。 这种情况可能会导致很难find错误。
如果jar文件位于Web应用程序文件夹中,则它们将由不同的类加载器加载,并且不会相互干扰。
从经验来看:这两个networking应用程序完全是相互隔离的 – 一个库不适用于另一个 – 从而回答你最初的问题 – 是的,他们会被加载两次。
要回答第二个问题,是否应该将这些库部署到Tomcat的共享目录中 – 我会说不,以下是原因:
如果将库Jar部署到共享位置(tomcat / server / lib),则该库的该版本将成为在该Tomcat实例下运行的所有Web应用程序的默认值。 从这个tomcat体系结构的概述中可以看出,类加载器在“链下”工作,单个Web应用程序的lib文件夹是引发类未发现exception之前查看的最后一个位置。 这在Tomcat 6和Tomcat 7中不是这样的:Web apps和lib文件夹中的任何类都将在共同之前被parsing,因此,这不会破坏在战争2中部署所有jar的其他应用程序。
因此,将共享库部署到该目录的问题在于,它打破了单个应用程序相互隔离的体系结构。 在你最初的例子中是好的,但是如果你想部署一个第三方应用程序(例如,如果你正在运行一个使用Portlet来处理特定内容的应用程序),你会立即遇到版本依赖问题 – 你的共享版本库对于第三方应用程序来说不是正确的,但是因为包已经被加载了,所以你会抛出exception向右和居中。
我们正在使用tomcat6,并find一个好方法,让tomcat塞满了我们所有web应用程序所需的通用库。
在conf / catalina.properties中编辑条目common.loader 。 例如追加一个文件夹与你喜欢分享“mylibs”
common.loader=${catalina.base}/lib,${catalina.base}/lib/*.jar, ${catalina.home}/lib,${catalina.home}/lib/*.jar, {catalina.home}/mylibs/*.jar
然后把所有的共同库放在那里。 完成。
为什么我们开始在所有webapps(WAR文件)中使用mylibs文件夹而不是WEB-INF / lib?
战争越过了50MB线后,部署开始变成了一场噩梦!
当有一个从未使用jar版本的webapp时,你仍然可以把它放到WEB-INF / lib中来覆盖你在mylib中的内容 。
如果你不希望你的图书馆加载两次:
- Tomcat 6:
$CATALINA_HOME/lib
- Tomcat 5:
$CATALINA_HOME/common/lib
(从问题中删除,并在这里复制,所以可以投票/评论)
PermGen堆的空间用于存储有关Java中的类的类和元数据。
错误java.lang.OutOfMemoryError:PermGen空间可能经常发生,因为我们在Apache Tomcat中加载大量重复的库任何人都可以分享它的细节