玻璃鱼域如何相互分离?

10

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

现在,在domain1中

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

同时,在 domain2 中

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

据我所知,GF及其所有域都在一个JVM实例中运行。而我不明白如何在一个JVM实例中分离系统属性。请问有人能解释一下吗?

注:我知道这可能是一个非常长的解释,因此我只询问主要原则以及按顺序能在互联网上阅读相关信息的解决方案/库名称。


我得到了一些关于我的答案的评论,现在我不太确定它是否真的正确。我已经更新了它,但如果你决定取消接受我的答案,我也不介意。我甚至考虑在这个问题上设置赏金...如果你对此感兴趣,请告诉我。 - GhostCat
@GhostCat 感谢您的通知。如果您能,请开始一个赏金 - 对我来说,这个问题仍然很重要和有趣。 - Pavel_K
赏金在那里! - GhostCat
好的...我的观点是:一开始看起来好像类加载机制是这个问题的答案。但现在我改变了主意。但这意味着单个JVM的系统属性必须相同。我看到行为有两种可能的原因:1)“GF和它的所有域都在一个JVM实例中运行”的想法可能是错误的。也许它们是两个JVM。_(我更喜欢这个。)_2)在代码的某个地方,在另一个地方读取之前,系统属性被覆盖(我认为不太可能)。 - Seelenvirtuose
真遗憾,我本希望这个赏金能在这里带来更多的赞数...希望你至少能让这个“10”有所作为... - GhostCat
2个回答

5
似乎理解“GF及其所有域在一个JVM实例中运行”是错误的。
根据GlassFish当前版本的文档(第3章):
一个域包含一组一起管理的GlassFish Server实例。[...] GlassFish Server实例是Java平台(Java虚拟机或JVM机器)上的单个虚拟机,在其中运行GlassFish Server。
这意味着,任何域的每个单个实例都在自己的JVM中运行!因此,它们都可以有自己不同的系统属性。
公平地说:在GlassFish中管理虚拟服务器的方法似乎共享一个JVM,但我认为您不是在谈论它们。

所以,我们开始吧。我希望赏金能为这里的所有内容带来更多的赞同...而不仅仅是问题本身。但无论如何... - GhostCat
你能说一个域创建一个 JVM 吗?(一个 JVM 为 domain1,一个 JVM 为 domain2),还是每个虚拟服务器都创建一个 JVM(一个 JVM 为 domain1-virtserver1,一个 JVM 为 domain1-virtserver2,一个 JVM 为 domain2-virtserver1,一个 JVM 为 domain2-virtserver2 等)? - Pavel_K

2
GlassFish、JBoss、WebSphere等产品“简单地”利用Java类加载机制进行隔离。通过使用多个类加载器,即使是静态类字段也可以存在“多次”,每个“域”都有自己特殊的版本。
请从这里那里开始阅读。
引用如下:
应用程序宇宙 - 每个Java EE应用程序都有其自己的类加载器宇宙,该宇宙加载应用程序中所有模块中的类。
此外,请参考这里
换句话说:尽管System类显然代表“系统视图”,但类加载机制应该使得为每个域提供不同的System类实例成为可能。从而在每个域特定的System类中具有特定于域的属性。但要准确:我找不到明确的证据来支持这一说法。关于这个话题,这里那里应该会有所帮助(后者表明甚至有方法来篡改系统类加载器)。
但是,更进一步思考,这个想法存在问题:实际上有两个类加载机制。有“系统/用户”类加载器和初始引导类加载器。
引导类加载器实际上是“烤”在JVM中的(例如,它是用本地代码实现的),并且无法替换。
而java.lang.System应该由引导类加载器加载!
因此,使用“类加载器魔术”启用“每个域”System属性是不可能的!
我看到的另一个选项是创建一个Java代理,拦截调用并操作其结果(请参见这里作为起点)。
但是,代理在引导完成后才会出现!
因此,唯一的逻辑结论(在排除所有选项后剩下的)是问题的前提是错误的!

不同“应用程序”在同一JVM上运行并给出不同的系统属性是完全不可能的。幸运的是,Seelenvirtuose的伟大答案证实了这个结论。


尽管你是正确的,OP 是在谈论系统属性。而这些通常是 VM 范围内的。你的 “答案” 没有解决这个问题。 - Seelenvirtuose
“类加载机制仍然可以为每个域提供不同的系统类实例。” => 你有任何证据吗?我的意思是...听起来没错(我不知道足够的信息来支持它),但一些验证文件会很好。(答案可能是正确的,但是...)我问这个问题,因为查看System类的源代码显示存在一些非常低级别的本地启动行为。 - Seelenvirtuose
@Seelenvirtuose 正如你所怀疑的那样,@GhostCat所说的声明是错误的。只有引导类加载器被允许在java.*命名空间中定义类,其中包括java.lang.System。因此,在整个JVM中只能加载一个System类。这在ClassLoader#defineClass方法的JavaDoc中有记录,该方法指出,如果尝试在以"java."开头的完全限定名称的包中定义类,则会抛出SecurityException。 - Neil Bartlett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接