【问题标题】:How glassfish domains are separated from each other?glassfish 域如何相互分离?
【发布时间】:2017-06-21 10:41:12
【问题描述】:

GlassFish 允许创建 N 个域。每个域都有自己的 Java 类(库等)和系统设置。

例如,我们有两个域 - domain1 和 domain2。

通过 GF Web 控制台 (http://localhost:4848) 为 domain1 - com.temp.foo=test1 设置了一个系统属性。除了通过 GF Web 控制台 (http://localhost:7575) 之外,还为 domain2 - com.temp.foo=test2 设置了一个系统属性。

现在,在域 1 中

System.out.println(System.getProperty("org.temp.foo"))
//returns `test1`

在域2中

System.out.println(System.getProperty("org.temp.foo"))
//returns `test2`

据我了解,GF 及其所有域都在一个 JVM 实例中运行。而且我不明白在 JVM 单独系统属性的一个实例中是如何实现的。谁能解释一下?

注意:我知道这可能是一个很长的解释,这就是为什么我只按照我可以在互联网上阅读的顺序询问主要原理和解决方案/库名称的原因。

【问题讨论】:

  • 我的回答得到了一些 cmets;我不确定它是否真的正确。我更新了它;但我不介意你决定不接受。我什至考虑在这个问题上悬赏……如果你对此感兴趣,请告诉我。
  • @GhostCat 感谢您的通知。如果可以,请开始赏金 - 这个问题对我来说仍然很重要且很有趣。
  • 赏金就在那里!
  • 嗯......我的意见:首先看起来类加载机制似乎是这个问题的答案。但现在我支持它。但这意味着对于单个 JVM,系统属性必须相同。我看到该行为的两个可能原因:1)“GF 及其所有域都在一个 JVM 实例中运行”的想法可能是错误的。也许它们是两个 JVM。 (我更喜欢这个。) 2)在代码中的某个地方,系统属性在被另一个地方读取之前被覆盖(我认为不太可能)。
  • 太糟糕了;我曾希望赏金会在这里引起更多的支持......希望你至少能算上“10”......

标签: java jakarta-ee glassfish


【解决方案1】:

似乎理解“GF及其所有域都在一个JVM实例中运行”是错误的。

根据 GlassFish 当前版本的documentation(第 3 章):

域包含一组受管理的 GlassFish Server 实例 一起。 [...] GlassFish Server 实例是 Java 平台(Java 虚拟机或 JVM 机器)在 GlassFish Server 所在的单个节点上 正在运行。

这意味着,任何域的每个实例都在其自己的 JVM 中运行!因此,它们都可以有自己不同的系统属性。

公平地说:GlassFish 中有管理虚拟服务器的方法,它们似乎共享一个 JVM,但我认为您不是在谈论它们。

【讨论】:

  • 那么,我们开始吧。我曾希望赏金会为这里的所有内容带来更多的支持……而不仅仅是问题本身。但无论如何......
  • 你能说 - 为一个域创建一个 jvm(一个 jvm 为 domain1,一个 jvm 为 domain2)或为每个虚拟服务器创建一个 jvm(一个 jvm 为 domain1-virtserver1,一个 jvm domain1-virtserver2,一个 jvm 用于 domain2-virtserver1,一个 jvm 用于 domain2-virtserver2 等等)?
【解决方案2】:

GlassFish、JBoss、WebSphere 等产品“简单地”利用 Java 类加载 机制来创建隔离。通过使用多个类加载器,即使是 static 类字段也可以“多次”存在;每个“域”都有其非常特殊的版本。

开始阅读here,例如there

Application Universe – 每个 Java EE 应用程序都有自己的类加载器 Universe,它加载应用程序中所有模块中的类。

除此之外,请查看this

换句话说:虽然 System 类显然代表了一个“系统视图”——类加载机制应该可以为每个域提供不同的 System 类实例。从而可以在每个特定于域的 System 类中具有特定于域的属性。但准确地说:我找不到明确的证据来支持这一说法。在这个话题上,herethere 应该会有所帮助(后者表示甚至有办法篡改 system 类加载器)。

但进一步思考,这个想法有一个问题:实际上有两个类加载机制。有“系统/用户”类加载器......和初始引导类加载器。

并且引导类加载器实际上是“烘焙”到 JVM 中(例如,它是在本机代码中实现的) - 它不能替换

并且 java.lang.System 应该由该引导类加载器加载!

所以不可能使用“classloader magic”来启用“per domain”系统属性!

我看到的另一个选项是创建一个 Java 代理来拦截调用并操纵其结果(请参阅here 作为起点)。

但又一次;代理“在”引导完成后来!

所以唯一合乎逻辑的结论(排除所有选项后剩下的):问题的前提一定是错误的!

不可能相同 JVM 上运行的不同“应用程序”会赋予不同的系统属性。幸运的是,Seelenvirtuose 的伟大 answer 证实了这一结论。

【讨论】:

  • 虽然你是对的,但 OP 是在谈论 系统属性。这些通常是 VM 范围的。您的“答案”没有解决这个问题。
  • “类加载机制仍然可以为每个域提供不同的 System 类实例。” => 你有什么证据吗?我的意思是……听起来不错(而且我不知道是否支持它),但是一些验证文件会很好。 (虽然分析器可能是正确的......)我问,因为查看 System 类的源代码表明存在一些非常低级别的本机启动行为。
  • @Seelenvirtuose 正如您所怀疑的,@GhostCat 的声明是错误的。仅允许引导类加载器在 java.* 命名空间中定义类,其中包括 java.lang.System。因此,整个 JVM 中只能加载一个 System 类。这在 ClassLoader#defineClass 方法的 JavaDoc 中有记录,该方法指出,如果尝试在包中定义一个具有以“java.”开头的完全限定名称的类,则会引发 SecurityException。
猜你喜欢
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-16
  • 1970-01-01
  • 2023-02-03
  • 1970-01-01
相关资源
最近更新 更多