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中加载大量重复的库任何人都可以分享它的细节