簡體   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