2013-10-11 176 views
5

我試圖初始化一個布爾類型的數組,其大小是一個10位整數。它一直在投擲OutOfMemoryException。我已經將eclipse堆空間的大小從256增加到了1024.有沒有什麼是我缺少的?java.lang.OutOfMemoryError:初始化數組時初始化Java堆空間

int size = 1000000000; 
boolean[] primesList = new boolean[size]; 
+4

你是否真的需要這麼多的空間? – Reddy

+0

先計數:大小* 4字節加上其他對象。使用[Buffer](http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html)代替 –

+0

@ajozwik你從哪裏得到大小* 4字節? – Kayaman

回答

11

的最大尺寸。

布爾數組元素需要1個字節而不是1個位的原因是(大多數)CPU體系結構不提供直接讀取和寫入單個內存位的功能。最小的個人電腦可以操縱8位。 JVM 可能會將這些位打包在一起,然後修改一下它會讀取該字節,修改它並將其寫回,但如果多個線程同時修改陣列,則這不起作用。

至於你的原始陣列,它是10億布爾值,每個一個字節,即10億字節或〜954 MB。所以一個1024 MB的堆應該足夠了(?)。也許它找不到一個連續的大塊內存,或者你沒有正確設置內存參數。打印Runtime.getRuntime().maxMemory()的值以找出Java正在使用的最大堆大小。對於1024 MB的參數應該是-Xmx1024M

最後說明:從Java 7開始,您可以在數字中使用下劃線以使其更具可讀性。所以你可以寫1_000_000_000而不是1000000000

2

docs

This data type represents one bit of information, but its "size" isn't something that's precisely defined.

如果考慮布爾至少一個字節,即1000000000字節,需要953MB存儲器來儲存陣列。

因此,這是唯一一個吃掉了953MB1024MB,可能會導致問題。

但是,在一個良好的世界,這用情況下不會要求我猜:)

+0

您在那裏添加了一個零,並且一個布爾值不會佔用一位,至少在這種形式下。 – Kayaman

+0

你錯算了。有10位數字,而不是11. –

+0

@ViktorOzerov是的,你是對的,多餘的零已被刪除。感謝您指點。 –

0

當啓動JVM需要傳遞一個-Xmx參數設置最大堆空間爲高。

還要注意的是陣列具有Integer.MAX_VALUE的

使用 java.util.BitSet,這將在該空間中的八分之一相比於使用 boolean陣列包的位的
0

您可以使用對象持有者來代替,避免需要一次分配所有空間 - 如果堆大小足夠大,可能會解決問題。您需要大量空間來容納陣列中的許多布爾值 - 確保爲堆空間設置最小和最大大小。 使用類似List的東西只在需要時填充值。如果你真的需要它作爲一個數組有轉換回來的方法(在Apache公共數組中的數組允許你使用Arrays.toPrimitive)。

0

布爾數組存儲爲字節:

https://forums.oracle.com/thread/2550321

我認爲你需要重新考慮你是如何做 - 生成數據結構,在千兆字節的順序大小超出當前硬件的能力。

1

只是要求更多的堆大小,例如-X1500M絕對有效。您的陣列佔用1000000000字節,但您需要更多地請求,因爲Java堆分爲新+舊代。

0

這可能是很好由於以下兩個原因:

  1. this文章,JVM不整XMX量分配給你的程序。其中一個倖存者空間佔用的空間會被打折,因爲JVM在內部使用它來進行一些簿記或臨時使用。這可能是1024 MB在這種情況下不夠用的原因,因爲您的陣列已經使用了954 MB。倖存者空間可能超過70 MB。根據this的文章,如果你的數據結構對於堆中的任何一代來說都太大(eden,from/to survivor),那麼你可以使用OOM來解決這個問題。 ,老根)。你可以使用-XX:+ PrintGCDetails,看看每一代人都有多少。所以,你必須不斷增加你的Xmx,直到它們中的至少一個(eden,from/to,old gen)足夠大以容納你的對象,否則你將不得不明確設置不同堆區的大小(例如 - XX:New gen for Young gen)。