2011-07-04 19 views
6

下面是MSDN:CLR/JVM是否爲所有正在運行的.net/java應用程序保留一個實習生池?

提取物的公共語言運行時通過維護表格節省 字符串存儲, 稱爲實習生池,它包含 單個參考聲明或創建 每個唯一 文字串以編程方式在您的程序中。 因此,在系統中僅存在一次具有特定值 字符串的實例,該實例只存在一次 。

例如,如果您分配相同 文字串幾個變量, 運行時檢索來自 實習生池相同 參考文本字符串,並將其分配給每個 變量。

實習生方法使用實習生池 來搜索等於str的 值的字符串。如果存在這樣的字符串, 其在實習池中的引用是 返回的。如果字符串不存在 ,則將對str的引用添加到 intern池中,然後返回該引用 。 ....如果您正在嘗試 減少您的應用程序分配的內存總量,請記住 ,表示實習字符串有兩個不需要的副作用 。首先,分配給實習字符串 對象 內存不容易被釋放 直至公共語言運行庫 (CLR)終止。

那麼,這是否意味着CLR爲所有正在運行的.net應用程序保留一個單一的實習生池? 例如:如果一個程序的創建一個字符串「測試」並在其他程序試圖創建另一個字符串字面量「測試」,使用相同的副本?同樣的問題也適用於JVM。

回答

2

CLR每個實例都保留一個實習生池。如果你繼續讀下去下來MSDN link

如果你想減少內存總量您的應用程序分配,請記住,實習字符串有兩個有害的副作用。首先,分配給interned String對象的內存不可能在公共語言運行庫(CLR)終止之前釋放。

對於Java這也是每啓動JVM。

然而,根據this article

這個神話進去神話2的相反的方向有些人相信的是內部化字符串留在內存中,直到JVM結束。這也許是真實的很久以前,但今天的內在串垃圾回收,如果有他們沒有更多的引用。請參閱下面的上述程序的稍微修改版本。它不時地清除對內部化字符串的引用。如果從jconsole執行程序執行,您將看到PermGen空間使用率升高和降低,因爲垃圾收集器回收未引用的內部化字符串使用的內存。

這意味着在Java interned字符串實際上可以得到GCed。

+1

你有鏈接嗎? –

1

不,因爲它不能。
每個應用程序都在其自己的虛擬內存空間中運行。您不能在兩個內存空間之間共享數據。
並考慮加載/卸載序列。這將變得非常複雜,你永遠不能刪除一個字符串。
還要注意你的報價,這部分:

聲明或程序中的程序創建的每一個獨特的文本字符串。


OK,只是讀一點點進一步指出MSDN頁:

CLR的參考實習 String對象的 申請後可以持續,甚至是你的應用程序 領域,終止。

+0

Holterman - 來自MSDN的行 - 首先,分配給interned字符串對象的內存不可能在公共語言運行庫(CLR)終止之前釋放。看起來像是CLR –

+0

@PK:我將它讀作「該程序的CLR實例」。 –

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

+0

他們是每個應用程序或整個JVM interned? –

+0

據我所知,每個JVM有一個池。然而,在正常情況下,您可能每個應用程序都有一個JVM--這取決於應用程序的定義。在服務器環境中,應用程序服務器將運行在一個JVM中,並可以託管多個(子)應用程序。 – Thomas

+0

我認爲問題在於JVM運行多個應用程序,對於每個應用程序(例如一個servlet容器)使用單獨的類加載器,是否有可能存在多個內部池。這無異於問我們是否可以用不同的類加載器多次加載java.lang.String。 –

0

正如我所瞭解的CLR,它是每運行一個,而不是每個AppDomain。從傑弗裏裏希特的「CLR通過C#」

注意,垃圾收集器不能釋放,內部哈希表是指因爲哈希表持有提到這些String對象的字符串。直到AppDomain被卸載或進程終止,內部哈希表引用的字符串對象才能被釋放。

這表明該表與AppDomain是分開的。

JVM沒有這個概念,所以沒有歧義。你可能有不同的類加載器,但很難想象你會爲String有不同的類加載器。

相關問題