Tomcat Classloader如何在同一JVM中分隔不同的Webapps对象作用域?

问题描述 投票:19回答:7

由于Tomcat可以一次加载多个Web应用程序,并且这些Web应用程序可以独立运行,并且不会互相干扰,因此它们可以在同一JVM中运行。因此,我对于tomcat如何在同一JVM中处理对象范围感到非常困惑。

例如,我在两个不同的Webapp中都有一个单例对象,并且tomcat将为每个生成两个不同的单例对象。我一直认为单例对象在同一JVM中只有一个对象,但是在tomcat JVM中可能有两个或更多。


我已经阅读了有关ClassLoader的一些信息,Tomcat具有自己的WebAppClassLoader来加载webapp。这是否意味着这里的Object Scope是ClassLoader还是我错了。有谁知道这件事,或者可以给我一些有关tomcat工作内存布局的信息吗?

java tomcat jvm
7个回答
31
投票

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

类的状态(如所有静态变量,字节码等)由类加载器确定,该类加载器加载该类(JVM中的类通过其完全限定的名称标识,而类加载器则加载该类。并非完全是一个范围,但作为范围的思考通常有助于更好地理解这一点。]

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

对于更复杂的情况,您将需要不同的行为。有时您想将库与代码混淆(例如eclipse中的插件或应用程序服务器中的Web应用程序)。

将程序与其他类隔离的基本思想是使用额外的类加载器加载那些类,并进行大量反射。如果您想阅读此内容,请查看ClassLoadersOSGI上的Oracle文档。

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


11
投票

请记住,Java中的类由其完全限定名称


6
投票

谈论单例时总是被遗忘的一件事是,单例只能有一个实例每个类加载器


5
投票

在正常的Java应用程序中,当要求类加载器加载类时,它首先将请求委托给它的父类加载器,如果父类加载器找不到所请求的类,则将其加载。

对于Web应用程序服务器,这略有不同。对于部署在诸如tomcat之类的Web应用程序服务器中的每个Web应用程序,通常都有不同的类加载器。对于Tomcat来说,如下图所示-


2
投票

JVM中类的“ ID”由完全限定的类名称和用于加载它的类加载器组成。这意味着,如果您通过不同的类加载器加载具有相同名称的两个类,它们将被视为不同的类。


0
投票

因此,对于容器中的类加载器,单例将是单例-在容器/ JVM中;因为一个容器/ JVM可能具有多个类加载器。


0
投票
  1. tomcat中的不同应用程序使用不同的类加载器进行分隔。例如,使用classLoaderA的app1,使用classloaderB的app2。
© www.soinside.com 2019 - 2024. All rights reserved.