我試圖初始化一個布爾類型的數組,其大小是一個10位整數。它一直在投擲OutOfMemoryException。我已經將eclipse堆空間的大小從256增加到了1024.有沒有什麼是我缺少的?java.lang.OutOfMemoryError:初始化數組時初始化Java堆空間
int size = 1000000000;
boolean[] primesList = new boolean[size];
我試圖初始化一個布爾類型的數組,其大小是一個10位整數。它一直在投擲OutOfMemoryException。我已經將eclipse堆空間的大小從256增加到了1024.有沒有什麼是我缺少的?java.lang.OutOfMemoryError:初始化數組時初始化Java堆空間
int size = 1000000000;
boolean[] primesList = new boolean[size];
的最大尺寸。
布爾數組元素需要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
。
從docs
This data type represents one bit of information, but its "size" isn't something that's precisely defined.
如果考慮布爾至少一個字節,即1000000000
字節,需要953MB
存儲器來儲存陣列。
因此,這是唯一一個吃掉了953MB
的1024MB
,可能會導致問題。
但是,在一個良好的世界,這用情況下不會要求我猜:)
您在那裏添加了一個零,並且一個布爾值不會佔用一位,至少在這種形式下。 – Kayaman
你錯算了。有10位數字,而不是11. –
@ViktorOzerov是的,你是對的,多餘的零已被刪除。感謝您指點。 –
當啓動JVM需要傳遞一個-Xmx參數設置最大堆空間爲高。
還要注意的是陣列具有Integer.MAX_VALUE的
使用 java.util.BitSet,這將在該空間中的八分之一相比於使用boolean
陣列包的位的
您可以使用對象持有者來代替,避免需要一次分配所有空間 - 如果堆大小足夠大,可能會解決問題。您需要大量空間來容納陣列中的許多布爾值 - 確保爲堆空間設置最小和最大大小。 使用類似List的東西只在需要時填充值。如果你真的需要它作爲一個數組有轉換回來的方法(在Apache公共數組中的數組允許你使用Arrays.toPrimitive)。
只是要求更多的堆大小,例如-X1500M絕對有效。您的陣列佔用1000000000字節,但您需要更多地請求,因爲Java堆分爲新+舊代。
這可能是很好由於以下兩個原因:
據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)。
你是否真的需要這麼多的空間? – Reddy
先計數:大小* 4字節加上其他對象。使用[Buffer](http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html)代替 –
@ajozwik你從哪裏得到大小* 4字節? – Kayaman