6

以下是MSDN的摘录:

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

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

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

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

4

4 回答 4

2

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

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

对于 Java,它也是您启动的每个 JVM。

但是根据这篇文章

这个神话与神话 2 的方向相反。有些人认为内部化的字符串会一直保留在内存中,直到 JVM 结束。很久以前可能是这样,但今天,如果没有对它们的引用,内部化的字符串就会被垃圾收集。请参阅下面的上述程序的略微修改版本。它会不时清除对内部化字符串的引用。如果您从 jconsole 跟踪程序执行,您将看到 PermGen 空间使用率上升和下降,因为垃圾收集器回收未引用的内部化字符串使用的内存。

这意味着在 Java 中,interned 字符串实际上可以被 GCed。

于 2011-07-04T08:18:46.153 回答
1

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

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


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

CLR 对实习字符串对象的引用可以在您的应用程序甚至您的应用程序域终止后持续存在。

于 2011-07-04T08:19:55.367 回答
0

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

于 2011-07-04T08:20:26.510 回答
0

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

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

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

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

于 2013-03-24T18:11:03.323 回答