跨JVM或Application实例或Tomcat实例的单例

如果我在Tomcat(或任何其他服务器)的单个实例上部署并运行相同应用程序的2个实例。 然后将创建一个单独的对象(Singleton类):

  1. 跨越Tomcat的单个实例(但对于同一应用程序的2个实例是常见的)或
  2. 跨应用程序实例(2个应用程序实例不同)

所以基本上我想要理解的是,每个JVM都会创建一个Singleton类的单个对象吗? 如果应用程序托管在Web服务器(或容器)上,这是如何工作的。

如果您有一个单例类,并且在Tomcat中运行两个使用此类的Web应用程序,则两个webapps将在运行Tomcat的JVM中获得此单例的2个不同实例。

但是,如果您的webapp将使用来自JRE或Tomcat共享库的单例,例如Runtime.getRuntime webapps将获得相同的Runtime实例。

这是因为Tomcat为webapps使用了单独的类加载器。 当webapp类加载器加载一个类时,它首先尝试在webapp类路径上找到它,如果找不到该类,则要求父类加载器加载该类。

单例通常仅与ClassLoader绑定。

因此,如果您的.war文件中有.class文件的单例,并且您多次部署此Web应用程序,则每个应用程序都会获得自己的单例。

另一方面,如果你的单例的.class文件在tomcat的类路径中,那么你只有一个实例。 此.class不属于特定的Web应用程序(它属于tomcat实例)。

如果两个位置都有单例,则它取决于类加载器层次结构,您可以在“父优先”或“首先是Web应用程序”之间进行选择。

通过确保始终为单例查询相同的ClassLoader ,可以创建这样的单例。 我在另一个答案中写了一个广泛的解释 。

据我所知,每个类加载器的单例是唯一的。 所以我认为你的问题的答案取决于容器加载Web应用程序的方式。

如果它为每个Web应用程序分配一个类加载器,那么您似乎会得到两个完全独立的单例对象。 如果它分配一个类加载器并且所有Web应用程序都使用它,那么它们共享相同的单一实例。

  • Tomcat为每个Web应用程序创建新的类加载器。
  • 因此,如果您的Singleton类存储在war文件中,则相同的war文件将在Tomcat容器中具有两个实例,即它为每个war文件创建两个单独的Singleton类。
  • 如果Singleton类位于Tomcat的共享库路径中,则Tomcat仅为两个应用程序创建一个Singleton实例。

JVM类比:

JVM就像大宅一样。 它包含组合家庭与几个应用程序和库。

ClassLoaders是系列成员,每个系列成员代表一个ClassLoader(作为委托层次结构而不是inhertance层次结构)。 注意:ClassLoader是类,它可以创建多个实例。

应用就像设备一样。 例如:洗衣机,冰箱,空气冷却器,Telivision,餐桌,沙发等……

图书馆每个人都有自己的图书馆。 如果没有找到父母的自由中的每一个搜索,那么在他自己的图书馆中搜索。

限制:如果父亲购买了他们的孩子可以使用的器具,但是他的父母和兄弟姐妹不能使用它。 每个应用程序可能使用相同库的不同版本。 即如果图书馆包含两本或两本以上版本的同一本书,则会先选择该书可用的图书。

每个家庭号码只能使用一个独特的设备。

在家里,我们可以使用相同版本的多件装置。 因此,JVM允许我们运行相同版本的多个应用程序。

垃圾收集器是Mansion中的一个服务器,它作为守护进程漫游,可以清除任何类型的对象。

静态变量的范围限制为每个ClassLoader一个。