繁体   English   中英

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

[英]Does the CLR/JVM keep one single intern pool for all running .net/java apps?

以下是MSDN 的摘录:

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

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

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

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

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

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

对于 Java,您也可以根据 JVM 开始。

但是根据这篇文章

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

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

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

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


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

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

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

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

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

JVM 没有这个概念,所以没有歧义。 您可能有不同的 class 加载器,但很难想象您会有不同的 class 加载器用于 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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM