Tomcat Classloader 如何在同一 JVM 中分离不同的 Webapps 对象范围?

2022-09-01 19:50:51

由于Tomcat可以一次加载多个web应用程序,并且这些Web应用程序可以单独工作,并且不会相互干扰,并且它们在同一个JVM中工作。所以我对tomcat如何处理同一JVM中的The Object范围感到非常困惑。

例如,我在两个不同的Web应用程序中都有一个单例对象,tomcat将为每个对象生成两个不同的单例对象。我一直认为单例对象在同一个JVM中只有一个对象,但在tomcat JVM中可能有两个或更多。


我已经阅读了一些关于ClassLoader的信息,Tomcat有自己的WebAppClassLoader来加载webapps。那么,这是否意味着这里的对象作用域是类加载器,还是我错了。有没有人知道这一点,或者可以给我一些关于tomcat工作记忆布局的信息?


答案 1

所有的秘密都在这些实例的背后。ClassLoader

类的状态(如所有静态变量、字节码等)由类装入器限定范围,类装入器装入该类(类在 JVM 中通过其完全限定的名称和装入类的类装入器来标识)。这并不完全是一个范围,但作为范围思考通常有助于更好地理解这一点)。

因此,如果一个类由两个不同的类加载器加载,则此类在VM中存在两次,它具有两组静态字段,可以具有不同的字节代码(如不同的方法实现)等等。请注意,这两个对象不能相互强制转换,即使它们的名称相同。“普通”Java 应用程序的所有类都由类装入器层次结构装入,并且每个类只装入一次。

对于更复杂的方案,您将需要不同的行为。有时,您希望将库与代码混淆(例如 eclipse 中的插件或应用程序服务器中的 Web 应用程序)隔离开来。

将程序与其他类隔离开来的基本思想是加载那些具有额外类加载器的程序并使用大量反射。如果你想阅读这篇文章,看看Oracle关于ClassLoadersOSGI的文档。

Tomcat(以及许多其他Web容器/应用程序服务器)使用单独的ClassLoader层次结构加载应用程序。这将所有类与其他(Web)应用程序隔离开来,从而也确保单例,不同的类版本和所有这些东西不会发生冲突。


答案 2

请记住,Java 中的类由其完全限定名装入它的类装入器标识。Tomcat 为您部署的每个上下文(Web 应用程序)使用单独的类装入器,从而将它们分开。此外,系统类装入器装入 tomcat 特定的库,JVM 引导加载器装入 Java 核心库。


推荐