2013-10-11 4 views
5

Я пытаюсь инициализировать массив булевых типов, размер которых составляет 10-значное целое число. Он продолжает метать OutOfMemoryException. Я увеличил размер кучи пространства затмения до 1024 с 256. Есть ли что-то, чего мне не хватает?java.lang.OutOfMemoryError: Java heap space при инициализации массива

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

Вам действительно нужно такое пространство? – Reddy

+0

Подсчитайте сначала: размер * 4 байта плюс другие объекты. Используйте [Буфер] (http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html) вместо –

+0

@ajozwik Откуда у вас размер * 4 байта? – Kayaman

ответ

11

Использование java.util.BitSet, который будет упаковать биты в одной восьмой части пространства по сравнению с использованием boolean массива.

Причина, по которой логические элементы массива принимают 1 байт вместо 1 бит, потому что (большинство) архитектуры ЦП не обеспечивают возможность прямого чтения и записи отдельных бит памяти. Меньшие единицы ПК могут работать с 8 битами. JVM может упаковать бит вместе, а затем изменить бит, он будет считывать байт, изменять его и записывать обратно, но это не работает, если несколько потоков одновременно изменяют массив.

Что касается вашего исходного массива, это 1 миллиард булевых, по одному байту, что составляет 1 миллиард байт или ~ 954 МБ. Итак, куча 1024 МБ должна быть достаточной (?). Возможно, он не может найти достаточно большой объем памяти или, возможно, вы не задали параметр памяти правильно. Распечатайте значение Runtime.getRuntime().maxMemory(), чтобы узнать максимальный размер кучи, который использует Java. Для 1024 МБ параметр должен быть -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 памяти для вашего массива.

Так что это единственный массив, который съедает 953MB из 1024MB, может быть, что вызвало проблему.

Но в хорошем мире этот вариант использования не потребуется, я предполагаю :)

+0

Вы добавили туда нуль, и логическое значение не принимает один бит, по крайней мере, в этой форме. – Kayaman

+0

Вы просчитались. Существует 10-значное число, а не 11. –

+0

@ViktorOzerov Да, вы правы, этот лишний ноль удален. Спасибо, что указал. –

0

При запуске виртуальной машины Java вы должны передать -Xmx параметр, чтобы установить максимальное пространство кучи, как выше.

Также отметим, что массивы имеют максимальный размер Integer.MAX_VALUE

0

Вместо этого вы можете использовать держатель объекта, избегая необходимости выделения всего пространства одновременно, что может обойти проблему, если размер кучи достаточно большой. Вам нужно много места для хранения таких булевых элементов в массиве - убедитесь, что минимальный и максимальный размер заданы для кучи. Используйте что-то вроде списка только для заполнения значений, когда это необходимо. Если вам действительно нужно это как массив, есть способы конвертировать назад (коллекция массивов в apache commons позволяет использовать Arrays.toPrimitive).

0

булевы массивы хранятся в виде байтов:

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

Я думаю, вам нужно переосмыслить то, как вы делаете это - создание структур данных с размерами в порядке гигабайта за пределами возможностей текущего оборудования.

1

Просто укажите размер кучи, например -X1500M, безусловно, работает. Ваш массив занимает 1000000000 байт, но вам нужно запросить больше, потому что куча Java делится на новые + старые поколения.

0

Это может быть очень хорошо благодаря следующим двум причинам:

  1. Согласно this статье, JVM не выделяет всю сумму XMX к вашей программе. Пространство, занимаемое одним из оставшихся в живых, дисконтируется, поскольку JVM использует его для внутреннего хранения или для временного использования. Это может быть причиной того, что 1024 МБ недостаточно в этом случае, так как ваш массив уже использует 954 МБ. Оставшееся в живых пространство может быть более 70 МБ. Увеличение Xmx может или не поможет, как объяснено ниже.

  2. Согласно статье this, у вас может быть OOM, если ваша структура данных слишком велика для любого из поколений в куче (eden, from/to survivor , старый ген). Вы можете использовать -XX: + PrintGCDETails и посмотреть, сколько получает каждый из поколений. Таким образом, вы должны продолжать увеличивать свой Xmx, пока, по крайней мере, один из них (eden, from/to, old gen) не будет достаточно большим, чтобы удерживать ваш объект, или вам придется явно задавать размер различных областей кучи (например, XX: NewSize for Young gen).

Смежные вопросы