2013-04-07 77 views
1
String samplel = "ToBeGarbageCollected"; 
String sample2 = samplel.substring(0, 1); 
samplel = null; 

我知道子串內部會保留原始字符串的引用。另一個字符串的子字符串是否會阻止父字符串被垃圾收集?

但通過明確定義samplelnull,sample1和sample2是否可用於垃圾回收?

我記得在某個地方看到父級對象顯式設置爲null所有子值都可用於垃圾收集。這會對上述情況有好處嗎? 我只是好奇,如果這是父母的孩子關係情況?如果沒有,這會導致sample1sample2可用於垃圾回收?

String samplel = "ToBeGarbageCollected"; 
String sample2 = new String(samplel .substring(0, 1)); 
samplel = null; 

回答

6

首先要說的是垃圾收集不會立即發生。因此,分配null任何東西不會/不能導致垃圾回收。什麼是可能確實會導致一個對象變爲無法訪問 ...並且這將使其成爲未來GC運行中垃圾收集的潛在候選者。


現在給你具體的例子。

重要說明:以下只適用於適用於較舊的JVM;即Java 7 update 5及更早的版本。在Java 7更新6中,他們更改String.substring(),以便目標字符串和生成的子字符串不共享後備數組。這消除了substring的潛在存儲泄漏問題。


substring方法不把參照原字符串的新的String。它實際上做的是保存對原始String的後備數組的引用;即包含字符的陣列。

但話雖如此,將null分配到samplel是不足以使整個原始字符串的狀態無法訪問。原始字符串的整個支持數組將保持可到達......這意味着它不會成爲垃圾收集的候選人。

但還有另一個複雜因素。您可以設置sample1爲字符串文字,並表示一個字符串文字String對象是總是到達(除非整個班級被卸載!)

但通過顯式定義樣品1爲空,將樣本1和樣本2是可用於垃圾收集?

原始sample1對象將保持完全可達的,並且sample2仍將是可達的,除非該變量超出範圍。

如果sample1不是文字,也沒有其他引用,那麼答案會不同。 sample1對象將無法訪問,但其後備陣列仍可通過sample2到達。


在第二個示例中,複製子字符串會導致創建新的字符串。並且保證新的String不會與原始String和臨時子字符串共享後備數組。在這種情況下,分配null是不必要的。

現在是否將sample1和sample2都用於垃圾回收?

對於sample1是文字的情況,答案與上述相同。

如果sample1不是文字,並且沒有其他引用,則sample1和臨時子字符串現在將無法訪問。


我只是想知道哪裏String構造是有幫助的。

理論上它會是。

在實踐中,它取決於GC最終是否可以繼續查找時是否仍然可以訪問引用......以及所討論的字符串是否足夠大並且足夠多以對內存使用量產生重大影響。

而且在實踐中,前提是通常不滿意,創造一個新的字符串像通常於事無補。

+0

他使用術語「可用於垃圾回收」是正確的:很明顯,OP知道垃圾回收不會立即發生,並且這一事實不會影響實際問題, 對? – 2013-04-07 01:45:15

+0

@NathanielFord - 我不清楚他是否理解這些詞的意思。我選擇以不能理解的方式回答問題。而且還讓其他錯過/不瞭解這一點的人也能理解答案。 – 2013-04-07 01:55:35

+0

@Suraj - 如果有線程訪問或能夠訪問一個對象,那麼它是可訪問的。這基本上是可達性意味着什麼。 – 2013-04-07 02:34:59

2

請記住,在Java String是不可變的。在這種情況下,sample1將被丟棄,但sample2從不指向sample1:它指向最初創建時調用substring的JVM中單獨保存的不可變字符串。

當您將sample1設置爲空時,它指向的內存可用於垃圾回收(假設沒有其他字符串保持相同的值並且沒有其他變量指向該位置)。當您使用new關鍵字(或通過賦值原語隱式地執行此操作)時,會在堆上分配新的內存(通常再次,字符串不可變並共享相同的內存)。如果沒有指針(讀取:任何指定的變量)指向給定的內存位置,則它可用於垃圾回收。請記住:在任何情況下,如果沒有對象的引用,它就可以用於垃圾回收。對象不是由分配給它們的變量名定義的,而是在內存中的位置,而變量名則作爲指向這些對象的指針(引用)。字符串有些不同,因爲它們是不可變的,並且JVM可能選擇不進行垃圾回收,原因與引用它們無關。

+0

所以你的意思是說。如果沒有線程在兩種情況下都訪問sample1,則它可用於GC。 – Suraj 2013-04-07 01:44:39

+1

是的,但認識到「字符串」是不可變的,它與普通對象的處理方式不同。 JVM可能不會以相同的方式垃圾收集它們,因爲它通常效率不高。 – 2013-04-07 01:46:03

+0

雅真字符串的處理方式不同,但子字符串方法將有一個原始字符串權的引用。所以不會阻止原始字符串樣本被垃圾收集。 – Suraj 2013-04-07 01:48:18

相關問題