2012-07-20 32 views
1

我寫了一個示例java應用程序,它分配內存,然後永遠運行。
爲什麼倖存者空間使用的內存爲0kbytes?!堆:倖存者空間

List<String> stringlist = new ArrayList<String>(); 

    while (true) { 
     stringlist.add("test"); 
     if (stringlist.size() >= 5000000) 
      break; 
    } 

    while (true) 
     for (String s : stringlist); 
+0

分享一些代碼?你如何衡量倖存者的空間? – 2012-07-20 16:57:08

+0

'0'是什麼意思?它是空的還是沒有幸存空間? – npe 2012-07-20 16:58:16

+0

我編輯了帖子,sry – gosua 2012-07-20 17:02:46

回答

7

因爲「測試」是一個字符串文字,它將在永久存儲器中結束而不是堆。 您創建的對象的內存大小爲5000000 + 4 * 2〜5MB,可輕鬆融入伊甸園空間。

修改

stringlist.add("test"); 

stringlist.add(new String("test")); 

,你會得到500萬* 4 * 2 = 38MB其中最有可能還是會融入伊甸園。您可以增加列表大小或字符串長度以確保您有幸存者。

3

"test"String文字和,不管它是如何存儲(這已經在Java開發過程中改變),重要的一點這裏,那它是一個單一的對象

Recall the Java Language Specification

...一個字符串文字總是指String類的相同實例。這是因爲字符串文字 - 或者更一般地,是常量表達式(§15.28)的值的字符串 - 被「拘留」,以分享獨特的情況下,使用該方法的String.intern

因此,有沒有新的String s在您的循環內創建,因爲"test"始終指示相同的String實例。當ArrayList的內部容量耗盡時,會發生唯一的堆變化。


最後所需ArrayList的內部陣列的存儲器依賴於一個對象引用的大小,通常是它的5000000*4 bytes爲32位的JVM和64位的JVM用壓縮糟糕和5000000*8 bytes對於64位的JVM不啓動壓縮糟糕。

有趣的點這裏是www.kdgregory.com描述:

如果你的對象是足夠大,它會直接在年老代創建。用戶定義的對象不會(不應該)具有觸發此行爲所需的成員數量的任何地方,但數組將會:在JDK 1.5中,大於半兆字節的數組直接進入持久生成。

這與和諧these words found on oracle.com

如果生存空間太小,複製集合直接溢出到年老代。

這給出了另一個原因,爲什麼更大的陣列可能不會出現在倖存者空間中。所以它取決於具體的配置,不管它們是不是因爲從Eden空間複製到Tenured Generation中而出現的,或者是在Tenured Generation中首先創建的。但沒有出現在倖存者空間的結果是相同的。


所以當以其default capacity of 10創建ArrayList,內部數組是小於該閾值,因此將被在每個容量擴印創建的下一個的。但是,在新陣列超過此閾值時,所有舊陣列都是垃圾,因此不會顯示爲「倖存者」。

因此,在第一個循環結束時,您只剩下一個剩餘數組,它的大小遠遠超過了閾值,因此繞過了Survivor空間。你的第二個循環不會向內存管理添加任何東西。它會創建臨時Iterator s,但這些永遠不會「生存」。

相關問題