2011-11-16 44 views
0

我聽說PermGC中存在字符串對象池,並且當字符串intern被執行時,它首先檢查該池是否存在等價的字符串對象,如果它不存在,它會創建一個並返回對池實例的引用。關於PermGC中的字符串對象池

但這是我的第一個問題。

我認爲這個對象是在堆上創建的,特別是在年輕一代中。如果它在少量垃圾收集期間存活下來,它就會轉移到老一代。任何人都可以解釋字符串對象如何進入Perm GC中存在的池中?

第二個問題:

String s =「test」; s =「test1」;

如果我將「test1」重新分配給引用s並繼續使用「test1」,這是否意味着「測試」(對年輕一代創建)將被垃圾收集?

第三個問題: 字符串對象池如何與運行時常量池相關?

謝謝。

回答

2

是什麼讓你認爲interned字符串首先是年輕一代? String#intern()方法是一種本地方法。一個實現當然很有可能將它直接移植到permgen中。

第二個問題:如果沒有其他引用"test"字符串實例,它有資格進行垃圾回收。同樣的故事,如果它被拘留。即使是一個不再有任何活動引用的interned字符串也可以被垃圾回收。不過,這可能不是舊式JVM中的情況。我想,它可以是特定於實現的。

至於第三個問題,我不知道。我所知道的是源代碼中的字符串文字被放置在同一個池中。如果要構造一個等於來自源的String常量的字符串,然後再嵌入它,則會返回用於表示常量的實例。把它看作是字符串文字已經被立即執行了。

編輯:只要再讀一下你最初的幾句話,我想我會看到混亂的原因。當你在一個字符串上調用intern(),並且池中還沒有相等的字符串時,那麼它首先不會構造一個等效的字符串。它只會將名爲intern()的實例移動到池中,而不是返回新的引用。 That's how it's stated in the JavaDoc

+0

你是說只有String s = new String(「test」);首先會在年輕一代上創建一個字符串對象? – user826323

+0

@ user826323那麼,這將導致年輕一代的一個對象。然後,如果你調用'intern()',那麼如果沒有相應的字符串,那麼該實例's'要麼將被放入permgen池中,要麼**或**將返回先前的池實例,給你兩個引用。但是如果你在代碼中有'String s ='test';',那麼你會在池中有效地測試'',因爲它是一個源代碼文字。 –

0

字符串去實習生池在兩種情況下:

  • 你顯式調用String對象
  • 你用文字(你給字符串的明確內容)初始化它實習生()方法,因爲Java會自動實施字符串文字。

池被組織爲一個表,一旦字符串被實現,它將被添加到池中,如果該值尚未存在,則會使用對現有條目的引用。

在你的情況下,「測試」應該去池中,而不是年輕的空間,無論如何清理不再引用的字符串也在那裏執行(我不能說它是否是用於堆,如果這種行爲是標準的)