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

时间:2013-07-18 10:43:45

标签: java tomcat jvm webserver singleton

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

  1. 跨Tomcat的单个实例(但对于同一应用程序的2个实例很常见)或
  2. 跨应用程序实例(2个应用程序实例不同)
  3. 所以基本上我想要理解,每个JVM都会创建一个Singleton类的单个对象吗?如果托管在Web服务器(或容器)上的应用程序,这是如何工作的。

5 个答案:

答案 0 :(得分:27)

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

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

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

答案 1 :(得分:20)

单身人士通常只与ClassLoader绑定。

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

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

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

答案 2 :(得分:4)

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:1)

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

JVM类比:

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

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

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

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

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

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

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

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

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