2009-04-29 39 views
1

當試圖發現我的機器,我遇到了一些有趣的結果上的Java String數組的最大尺寸,這裏是代碼,這裏的內存分配是怎麼回事?

String [] max; 
    int i = 15444000; 
    while(true){ 
     try{ 
     max = new String[i]; 
     System.gc(); 
     Thread.sleep(10); 
     }catch(InterruptedException e){} 
    i += 1; 
    System.out.println(i); 
    } 

每當我運行此代碼的輸出使得投擲前OutOfMemoryError異常。這使我認爲,我的機器上的一個Java String數組的最大尺寸爲,但是如果我更換

int i = 15444000; 

int i = 15444037; // or any i between 15444037 and 15444002 

的OutOfMemoryError錯誤立即發生。這是爲什麼,我的機器上Java String數組的真正最大大小是多少?

+0

你分配給JVM多少內存? – CookieOfFortune 2009-04-29 22:05:51

+0

作爲Cookie指出,GC是如此不可預測,以至於這樣的測試最終並不意味着很多。 – 2009-04-29 22:16:57

回答

2

您將能夠分配的陣列的最大大小取決於虛擬機的最大內存配置的大小。您可以使用-Xmxcommand line argument更改最大值。

而且http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html#gc()狀態

調用gc方法表明,朝着爲了使內存回收未使用的對象的Java虛擬機的努力,他們目前佔據可快速重用。當控制從方法調用返回時,Java虛擬機已盡最大努力從所有被丟棄的對象中回收空間。

所以你的差異可能是因爲GC沒有每次(Java虛擬機已經回收空間盡力而爲)清理相同的方式。

1

我想可能會發生什麼,這只是一個猜測,是JIT(即時編譯器)可能會優化一些內存?第二個猜測是垃圾回收會在循環再次運行之前釋放一點點內存。嘗試在分配數組之前添加垃圾回收。

-1

那麼,你可以爭辯很多事情,但我認爲正確的答案是「誰在乎?」。對於你的配置最大限度的問題的答案是「約1500萬」。如果您真的想要將堆分配降至最後4個字節,請使用匯編程序編寫...

P.S. 可能正在發生的事情包括早期在維護線程中使用的對象,一旦程序運行了一段時間,這些對象就變爲垃圾收集。另一個海報暗示的JIT優化的另一個現象也是可能的:有一些線程開始在堆上分配小對象,然後在某些時候JIT被優化以在寄存器/堆棧中「分配」它們。但說實話,除非你發現陣列大小可以突然減半,否則我不會太擔心。

0

當你以略小的尺寸運行時,GC可以從年輕/伊甸園/倖存者那一代收集記憶,並將其轉移到終身代。大數組的分配是在終身代中進行的。由於GC先前已將物體移入終身區域,因此它現在的容量較小。

可能。完全取決於實施和時間安排。像這樣的大分配最好通過NIO直接分配的緩衝區完成。

0

不,從您發佈的代碼中沒有任何洞察力或真實性。如果增加可用的最大堆空間,則可以使陣列長度更高。

另一件值得了解的事情是:調用System.gc()並不意味着垃圾收集器運行。這只是一個建議。