CLR / JVM是否为所有正在运行的.net / java应用程序保留一个单一的实习池?

以下是MSDN的摘录:

公共语言运行库通过维护一个名为intern pool的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文字字符串的单个引用。 因此,具有特定值的文字字符串实例仅在系统中存在一次。

例如,如果将相同的文字字符串分配给多个变量,则运行时将从实习池中检索对文字字符串的相同引用,并将其分配给每个变量。

Intern方法使用实习池来搜索等于str值的字符串。 如果存在此类字符串,则返回其在实习池中的引用。 如果该字符串不存在,则将对str的引用添加到实习池中,然后返回该引用。 ….如果您正在尝试减少应用程序分配的内存总量,请记住,实习字符串有两个不需要的副作用。 首先,在公共语言运行时(CLR)终止之前,不太可能释放为被占用的String对象分配的内存。

那么,这是否意味着CLR为所有正在运行的.net应用程序保留一个单一的实习池? 示例:如果程序A创建字符串文字“Test”,并且如果另一个程序尝试创建另一个字符串文字“Test”,则使用相同的副本? 同样的问题也适用于JVM。

CLR为每个实例保留一个实习池。 如果您在MSDN链接中进一步阅读:

如果您尝试减少应用程序分配的内存总量,请记住,实习字符串有两个不需要的副作用。 首先,在公共语言运行时(CLR)终止之前,不太可能释放为被占用的String对象分配的内存。

对于Java,您也可以从每个JVM开始。

但是根据这篇文章 :

这个神话与神话的方向相反2.有些人认为内化的字符串会留在内存中,直到JVM结束。 很久以前它可能是真的,但是如果没有更多的引用,今天内部化的字符串是垃圾收集的。 请参阅下面的程序的略微修改版本。 它会不时清除对内部化字符串的引用。 如果您遵循jconsole中的程序执行,您将看到PermGen空间使用量上下变化,因为垃圾收集器回收了未引用的内化字符串使用的内存。

这意味着在Java中,实习字符串实际上可以获得GCed。

不,因为它不能。
每个应用程序都在自己的虚拟内存空间中运行 您无法在两个内存空间之间共享数据。
并考虑加载/卸载序列。 它会变得非常复杂,你永远不会删除一个字符串。
另请注意这部分报价:

在程序中以编程方式声明或创建的每个唯一文字字符串。


好的,只需在该MSDN页面上进一步阅读:

在您的应用程序甚至应用程序域终止后,CLR对interned String对象的引用可以保留。

至于Java,是的。 字符串文字按每个JVM保存在池中。 来自String#intern()的JavaDoc的摘录: All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification All literal strings and string-valued constant expressions are interned. String literals are defined in §3.10.5 of the Java Language Specification

据我了解CLR,它是每个运行时一个,而不是每个AppDomain。 来自Jeffrey Richter的“CLR Via C#”

请注意,垃圾收集器无法释放内部哈希表引用的字符串,因为哈希表包含对这些String对象的引用。 在卸载AppDomain或进程终止之前,无法释放内部哈希表引用的字符串对象。

这表明该表与AppDomain是分开的。

JVM没有这个概念,所以没有歧义。 您可能有不同的类加载器,但很难想象您将为String提供不同的类加载器。