【问题标题】:Webapp classpaths and classes being loaded into heapWebapp 类路径和加载到堆中的类
【发布时间】:2011-01-16 22:24:41
【问题描述】:

如果我有两个 webapp,它们的 web-inf/lib 目录中都有相同的第三方库 jar,比如 log4j .....当第一个 webapp 加载并创建 log4j 类时,这个类被加载到堆中。当第二个 webapp 加载并尝试加载 log4j 类时,它会在堆中找到该类并使用该类吗?或者它将自己的类副本加载到堆中?

【问题讨论】:

    标签: java classpath


    【解决方案1】:

    嗯,我认为这主要是一个 ClassLoader 问题,它仍然取决于您使用的应用程序服务器,但我猜他们中的大多数使用单个 JVM 并为每个正在运行的 webapp 保留一个 ClassLoader,以便您可以使用不同的 webapp同一 jar/clases 的不同版本一起运行。

    例如,在 tomcat 中,如果您需要一些共享库,您可以使用 /tomcat/shared/lib 文件夹,您可以在其中放置所有 Web 应用都可以访问的所有 jar。

    否则是的,不同的 webapp 不会共享同一个堆,这意味着 webapp 可以访问由运行在同一应用程序服务器中的其他 webapp 创建的对象

    【讨论】:

    • 最后一句话,如果他们不共享同一个堆,那是不是意味着他们不能访问其他 webapps 创建的对象?如果他们在同一个堆中,他们只能访问其他人,对吗?还是我误会了……
    • 井类定义存储在永久代(非堆)空间中。现在堆空间包含类的实例,然后是您使用“新”创建的任何对象。现在从应用程序服务器的角度来看,我不能确定内部是如何工作的,但我猜它会表现得“好像”你会为每个 webapp 分配一个 JVM,以便不让 webapps 交互彼此之间。因此,给定的 webapp 无法访问另一个 webapp 的内存空间。
    • 现在如果你使用tomcat,多个webapp将共享同一个JVM,因此将共享同一个内存空间。我仍然看不到一个 webapp 可以在没有引用的情况下访问另一个 webapp 创建的对象。对于您的 Log4J 示例,您的两个 webapps 将拥有自己的 ClassLoaders,然后两者都有自己的 log4j 类及其一个实例(再次,使您拥有使用 Log4J v2 的 webapp A 和 webapp B Log4j v3 例如) .
    【解决方案2】:

    不,不应该。

    在堆上加载的事实类在这里没有任何意义。因为每个类加载器都维护自己加载的类列表。

    但是,类加载器也被组织成一棵树,它们应该要求其父类加载器首先尝试加载类,如 ClassLoader 类的 javadoc 中所述。

    ClassLoader 类使用委托模型来搜索类和资源。 ClassLoader 的每个实例都有一个关联的父类加载器。当请求查找类或资源时,ClassLoader 实例将在尝试查找类或资源本身之前将对该类或资源的搜索委托给其父类加载器。

    但是,网络服务器通常不遵循这种委托模型,以避免网络服务器本身使用的库被网络应用程序拾取。 (此行为有时是可配置的,但这取决于您使用的网络服务器。)

    所以实际上每个 webapp 都应该有自己独立的类空间,独立于所有其他 webapp,因此它们甚至可以毫无问题地使用同一个库的两个不同版本。

    另一个重要的教训是,由两个不同的类加载器加载的同一个类文件实际上是堆中的两个独立类,一个类的对象将与另一个类不兼容。

    【讨论】:

      猜你喜欢
      • 2011-01-26
      • 2010-09-12
      • 2011-03-21
      • 2011-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-21
      • 2011-06-28
      相关资源
      最近更新 更多