简体   繁体   English

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

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

The following is an extract from MSDN:以下是MSDN 的摘录:

The common language runtime conserves string storage by maintaining a table, called the intern pool, that contains a single reference to each unique literal string declared or created programmatically in your program.公共语言运行时通过维护一个称为实习池的表来保存字符串存储,该表包含对程序中以编程方式声明或创建的每个唯一文字字符串的单个引用。 Consequently, an instance of a literal string with a particular value only exists once in the system.因此,具有特定值的文字字符串的实例在系统中只存在一次。

For example, if you assign the same literal string to several variables, the runtime retrieves the same reference to the literal string from the intern pool and assigns it to each variable.例如,如果您将相同的文字字符串分配给多个变量,则运行时会从实习池中检索对文字字符串的相同引用并将其分配给每个变量。

The Intern method uses the intern pool to search for a string equal to the value of str. Intern 方法使用实习池来搜索等于 str 值的字符串。 If such a string exists, its reference in the intern pool is returned.如果存在这样的字符串,则返回其在实习池中的引用。 If the string does not exist, a reference to str is added to the intern pool, then that reference is returned.如果字符串不存在,则将对 str 的引用添加到实习池,然后返回该引用。 .... If you are trying to reduce the total amount of memory your application allocates, keep in mind that interning a string has two unwanted side effects. .... 如果您尝试减少应用程序分配的 memory 的总量,请记住,插入字符串有两个不需要的副作用。 First, the memory allocated for interned String objects is not likely be released until the common language runtime (CLR) terminates.首先,在公共语言运行时 (CLR) 终止之前,分配给实习字符串对象的 memory 不太可能被释放。

So, does this mean that CLR keeps one single intern pool for all running .net apps?那么,这是否意味着 CLR 为所有正在运行的 .net 应用程序保留一个实习生池? Example: if a program A creates a string literal "Test" and if another program tries to create another string literal "Test", the same copy is used?示例:如果程序 A 创建了一个字符串文字“Test”,并且如果另一个程序尝试创建另一个字符串文字“Test”,则使用相同的副本? The same question also applies to JVM.同样的问题也适用于 JVM。

The CLR keeps an intern pool per instance. CLR 为每个实例保留一个实习生池。 If you read further down the MSDN link :如果您进一步阅读MSDN 链接

If you are trying to reduce the total amount of memory your application allocates, keep in mind that interning a string has two unwanted side effects.如果您尝试减少应用程序分配的 memory 的总量,请记住,插入字符串有两个不需要的副作用。 First, the memory allocated for interned String objects is not likely be released until the common language runtime (CLR) terminates.首先,在公共语言运行时 (CLR) 终止之前,分配给实习字符串对象的 memory 不太可能被释放。

For Java it's also per JVM you start.对于 Java,您也可以根据 JVM 开始。

However according to this article :但是根据这篇文章

This myth goes in the opposite direction of myth 2. Some people belive that internalized strings stay in the memory until the JVM ends.这个神话与神话 2 的方向相反。有些人认为内部化的字符串会保留在 memory 中,直到 JVM 结束。 It may have been true a long time ago, but today the internalized strings are garbage collected if there are no more references to them.很久以前可能是这样,但今天,如果没有对它们的引用,内部化的字符串就会被垃圾收集。 See below a slightly modified version of the program above.请参阅下面的上述程序的略微修改版本。 It clears the references to internalized strings from time to time.它会不时清除对内部化字符串的引用。 If you follow the program execution from jconsole, you will see that the PermGen space usage goes up and down, as the Garbage Collector reclaims the memory used by the unreferenced internalized strings.如果您从 jconsole 跟踪程序执行,您将看到 PermGen 空间使用率上升和下降,因为垃圾收集器回收未引用的内部化字符串使用的 memory。

Which means in Java interned strings can actually get GCed.这意味着在 Java 中,实习字符串实际上可以得到 GC。

No, because it can't. 不,因为它不能。
Each app runs in its own virtual memory space. 每个应用程序都在其自己的虚拟 memory 空间中运行。 You cannot share data between two memory spaces. 您不能在两个 memory 空间之间共享数据。
And consider the loading/unloading sequences. 并考虑装载/卸载顺序。 It would become very complicated and you could never remove a string. 它会变得非常复杂,您永远无法删除字符串。
Also note this part of your quote:另请注意您报价的这一部分:

each unique literal string declared or created programmatically in your program.在程序中以编程方式声明或创建的每个唯一文字字符串。


OK, just reading a little further on that MSDN page:好的,只需在该 MSDN 页面上进一步阅读:

the CLR's reference to the interned String object can persist after your application, or even your application domain, terminates. CLR 对实习字符串 object 的引用可以在您的应用程序甚至您的应用程序域终止后持续存在。

As I understand for the CLR it is one per runtime, not per AppDomain.据我了解,对于 CLR,它是每个运行时一个,而不是每个 AppDomain。 From Jeffrey Richter's "CLR Via C#"来自 Jeffrey Richter 的“CLR Via C#”

Note that the garbage collector can't free the strings that the internal hash table refers to because the hash table holds the reference to those String objects.请注意,垃圾收集器无法释放内部 hash 表引用的字符串,因为 hash 表包含对这些字符串对象的引用。 String objects referred to by the internal hash table can't be freed until the AppDomain is unloaded or the process terminates.在卸载 AppDomain 或进程终止之前,无法释放内部 hash 表引用的字符串对象。

This suggests that the table is separate from the AppDomain.这表明该表与 AppDomain 是分开的。

JVM doesn't have this concept so there is no ambiguity. JVM 没有这个概念,所以没有歧义。 You may have different class loaders, but it is hard to imagine you would have different class loaders for String.您可能有不同的 class 加载器,但很难想象您会有不同的 class 加载器用于 String。

As for Java, yes.至于Java,是的。 String literals are kept in a pool per JVM.每个 JVM 将字符串文字保存在一个池中。 Excerpt from the JavaDoc of 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摘自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