53

我在tomcat/webapps文件夹下有两个应用程序。

tomcat/webapps/App1
tomcat/webapps/App2

两个应用程序共享相同的库。例如存储在tomcat/webapps/App1/WEB-INF/lib.

两个库是否都在内存中加载了两次?

我应该把这些共享库放进去tomcat/server/lib吗?

4

6 回答 6

43

正如您在此处看到的,Tomcat 在您的服务器上为每个 webapp 创建一个类加载器。因此,如果你有 webapp1 和 webapp2 共享同一个库,那么这个库确实会被加载两次。

如果您的 Tomcat 服务器上运行的所有Web 应用程序都共享该库,您最终可以将该库放在公共目录 (tomcat-dir/common/lib)中。

于 2008-11-06T08:37:52.143 回答
29

我不建议将 jar 文件放在共享文件夹中。例如,假设您将来需要部署第三方应用程序,该应用程序在 WEB-INF 文件夹中有更新版本的 jar 文件。对于这个应用程序,jar 的类将被加载两次(即使它们具有相同的名称),一个来自共享文件夹,另一个来自 web 应用程序文件夹。这种情况可能会导致很难找到错误。

如果 jar 文件位于 web 应用程序文件夹中,则它们由单独的类加载器加载,并且不会相互干扰。

于 2008-11-06T10:13:15.383 回答
8

从经验来看:这两个网络应用程序完全相互隔离——一个应用程序的库没有在另一个应用程序中使用——因此回答你最初的问题——是的,它们会被加载两次。

要回答您的第二个问题,您是否应该将这些库部署到 Tomcat 的共享目录中 - 我会说不,原因如下:

如果您将库 Jar 部署到共享位置(tomcat/server/lib),那么该版本的库将成为在该 Tomcat 实例下运行的所有 Web 应用程序的默认版本。正如您从tomcat 体系结构的概述中看到的那样,类加载器“沿着链”工作,单个 web 应用程序的 lib 文件夹是它在引发未找到类的异常之前查看的最后一个位置。这在 Tomcat 6 和 Tomcat 7 中并非如此:web 应用程序库和类文件夹中的任何类都将在公共类之前解析,因此,这不会破坏在 war 2中部署所有 jar 的其他应用程序。

因此,将共享库部署到该目录的问题在于,它破坏了各个应用程序相互隔离的体系结构。在您的初始示例中很好,但是如果您想要部署第三方应用程序(例如,如果您正在运行使用 Portlet 来处理特定内容的应用程序),您会立即遇到版本依赖性问题 - 您的库的共享版本可能对于第三方应用程序不正确,但由于包已经加载,你会在左右和中间抛出异常。

于 2008-11-06T08:49:04.570 回答
6

我们正在使用tomcat6,并找到了一种让 tomcat 填充我们所有 webapps 所需的通用库的好方法。

在conf/catalina.properties中编辑common.loader条目。例如,附加一个附加文件夹,其中包含您喜欢共享的 jar '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?

WAR 突破 50MB 线后,部署开始成为一场噩梦!

当有一个没有 jar 版本的 webapp 时,您仍然可以将其放入WEB-INF/lib以覆盖您在mylibs中的内容。

于 2014-07-01T15:46:11.320 回答
4

如果您不希望您的库加载两次,请将它们放入:

  • 雄猫 6:$CATALINA_HOME/lib
  • 雄猫 5:$CATALINA_HOME/common/lib

(从问题中删除并复制到此处,以便对其进行投票/评论)

于 2015-02-02T03:04:53.173 回答
0

堆的 PermGen 空间用于存储 Java 中的类和关于类的元数据。

错误 java.lang.OutOfMemoryError: PermGen space 可能经常发生,因为我们在 apache tomcat 中加载了大量重复库,任何人都可以详细分享

于 2015-12-04T05:37:10.250 回答