Почему я получаю OutOfMemoryError при вставке 50 000 объектов в HashMap?

просто попробуйте это.

вам нужно открыть соединение с помощью connection.open() на объекте SqlCommand.Connection перед выполнением ExecuteNonQuery()

13
задан Frank Krueger 24 October 2008 в 19:53
поделиться

10 ответов

Можно увеличить максимальный размер "кучи" путем передачи-Xmx128m (где 128 число мегабайтов) к Java. Я не могу помнить размер по умолчанию, но он ударяет меня, что это было что-то довольно маленькое.

можно программно проверить, сколько памяти доступно при помощи Время выполнения класс.

// Get current size of heap in bytes
long heapSize = Runtime.getRuntime().totalMemory();

// Get maximum size of heap in bytes. The heap cannot grow beyond this size.
// Any attempt will result in an OutOfMemoryException.
long heapMaxSize = Runtime.getRuntime().maxMemory();

// Get amount of free memory within the heap in bytes. This size will increase
// after garbage collection and decrease as new objects are created.
long heapFreeSize = Runtime.getRuntime().freeMemory();

(Пример от Альманах Java-разработчиков )

Это также частично обращено в Часто Задаваемые Вопросы О Java HotSpot VM, и в страница .

Java 6 GC Tuning
21
ответ дан Michael Myers 24 October 2008 в 19:53
поделиться
  • 1
    @quinnapi ха-ха 2 года спустя и I' m получение той же проблемы. Я просто понял, что читал свой собственный ответ. Раздражающий! – Carlo 1 July 2011 в 20:46

Некоторые люди предлагают изменить параметры HashMap для закручивания требований к памяти. Я предложил бы мера вместо того, чтобы предположить ; это могло бы быть что-то еще вызывающее OOME. В частности, я предложил бы использовать или Профилировщик NetBeans или VisualVM (который идет с Java 6, но я вижу, что Вы застреваете с Java 5).

7
ответ дан Michael Myers 24 October 2008 в 19:53
поделиться
  • 1
    @Daniel, Только если все Ваши функции являются шаблонными функциями. Иначе можно сойти с рук перемещение некоторых функций и хранения .cpp файла. – strager 16 March 2009 в 01:03

Реализации обычно поддерживаются массивами. Массивы являются блоками фиксированного размера памяти. hashmap реализация запускается, храня данные в одном из этих массивов на данной способности, скажите 100 объектов.

, Если это заполняет массив и Вы продолжаете добавлять, возражает, что карта должна тайно увеличить свой размер массива. Так как массивы фиксируются, это делает это путем создания совершенно нового массива, в памяти, наряду с современным массивом, который немного больше. Это упоминается как рост массива. Тогда все объекты от старого массива копируются в новый массив, и старый массив разыменовывается с надеждой, это будет собрано "мусор", и память освобождена в какой-то момент.

Обычно код, который увеличивает способность карты путем копирования объектов в больший массив, является причиной такой проблемы. Существуют "немые" реализации и умные, которые используют фактор роста или коэффициент загрузки, который определяет размер нового массива на основе размера старого массива. Некоторые реализации скрывают эти параметры, и некоторые не делают так, Вы не можете всегда устанавливать их. Проблема состоит в том, что, когда Вы не можете установить его, это выбирает некоторый коэффициент загрузки по умолчанию, как 2. Таким образом, новый массив является дважды размером старого. Теперь Ваш, предположительно, 50k карта имеет вспомогательный массив 100k.

Надеются видеть, можно ли уменьшить коэффициент загрузки вниз до 0,25 или что-то. это вызывает больше коллизий карты хеша, который повреждает производительность, но Вы поражаете узкое место памяти и должны сделать так.

Использование этот конструктор:

( http://java.sun.com/javase/6/docs/api/java/util/HashMap.html#HashMap (интервал , плавание))

3
ответ дан Josh 24 October 2008 в 19:53
поделиться
  • 1
    Comeau делает я верю. И современная версия MSVC могла бы , но я haven' t проверил что самостоятельно. – vava 16 March 2009 в 01:29

Вероятно, необходимо установить флаг-Xmx512m или некоторое большее число когда стартовый Java. Я думаю, что 64 МБ являются значением по умолчанию.

Отредактированный для добавления: после выяснения, сколько памяти объекты на самом деле используют с профилировщиком, можно хотеть изучить слабые ссылки или мягкие ссылки, чтобы удостовериться, что Вы случайно не держите часть в заложниках своей памяти из сборщика "мусора", когда Вы больше не используете их.

2
ответ дан JasonTrue 24 October 2008 в 19:53
поделиться
  • 1
    Последний VS2008 doesn' t поддерживают ключевое слово экспорта все же. кажется, что парни MS зарезервировали это ключевое слово для будущей поддержки: предупреждение C4237: ' export' ключевое слово еще не поддерживается, но резервируется для будущего использования – Baiyan Huang 16 March 2009 в 02:53

Другая вещь попробовать, если Вы знаете количество объектов заранее, состоит в том, чтобы использовать HashMap (международная способность, двойной коэффициент загрузки) конструктор вместо без аргументов по умолчанию, который использует значения по умолчанию (16,0.75). Если число элементов в Вашем HashMap превысит (способность * коэффициент загрузки) тогда, то основной массив в HashMap будет изменен к следующему питанию 2, и таблица будет перефразирована. Этот массив также требует непрерывной области памяти так, например, если Вы удвоитесь от 32768 до 65 536 массивов размера, то Вам будет нужен блок 256 КБ свободной памяти. Для предотвращения дополнительных штрафов выделения и перефразирования просто используйте большую хэш-таблицу от запуска. Это также уменьшит шанс, что у Вас не будет непрерывной области памяти достаточно большой для установки карте.

3
ответ дан sk. 24 October 2008 в 19:53
поделиться

Пространство "кучи" Java ограничено по умолчанию, но это все еще звучит как экстремальное значение (хотя, насколько большой Ваши 50 000 сегментов?)

я подозреваю, что у Вас есть некоторая другая проблема, как массивы в наборе, становящемся слишком крупными, потому что все присвоено в тот же "слот" (также выполнение влияния, конечно). Однако это кажется маловероятным, если Ваши точки равномерно распределены.

я задаюсь вопросом хотя, почему Вы используете HashMap, а не TreeMap? Даже при том, что точки являются двумерными, Вы могли разделить их на подклассы со сравнить функцией и затем регистрируете (n) поиски.

1
ответ дан Uri 24 October 2008 в 19:53
поделиться
  • 1
    Хорошая идея. Но что относительно того, чтобы анализировать " LPD data" или независимо от того, что проникает через порт? – bzlm 19 February 2009 в 09:23

Неявный в этих ответах это, что Java имеет фиксированный размер для памяти и не растет вне настроенного максимального размера "кучи". Это, в отличие от этого, скажем, C, где это ограничило только машиной, на которой это выполняется.

1
ответ дан davetron5000 24 October 2008 в 19:53
поделиться

По умолчанию JVM использует ограниченное пространство "кучи". Предел является зависящей от реализации JVM, и не ясно, какую JVM Вы используете. На ОС кроме Windows 32-разрядной JVM Sun на машине с 2 Гбитами или больше будет использовать максимальный размер "кучи" по умолчанию 1/4 физической памяти, или 512 Мбит в Вашем случае. Однако значение по умолчанию для "клиентского" режима JVM является максимальным размером "кучи" на только 64 Мбита, который может быть тем, с чем Вы столкнулись. JVM другого поставщика может выбрать различные значения по умолчанию.

, Конечно, можно определить предел "кучи" явно с -Xmx<NN>m опция к java, где <NN> число мегабайтов для "кучи".

Как приблизительный подсчет, Ваша хэш-таблица должна только использовать приблизительно 16 Мбит, таким образом, должны быть некоторые другие большие объекты на "куче". Если бы Вы могли бы использовать Comparable, вводят TreeMap, который сохранил бы некоторую память.

См. "Эргономика в 5,0 JVM" для получения дополнительной информации.

1
ответ дан erickson 24 October 2008 в 19:53
поделиться

Также мог бы хотеть смотреть на это:

http://java.sun.com/docs/hotspot/gc/

1
ответ дан Allain Lalonde 24 October 2008 в 19:53
поделиться

Случайная мысль: блоки хеша, связанные с HashMap, не являются особенно эффективной памятью. Можно хотеть испытать TreeMap как альтернативу и видеть, обеспечивает ли он все еще достаточную производительность.

1
ответ дан Kevin Day 24 October 2008 в 19:53
поделиться
  • 1
    Обычно 515, это как большинство вещей, является определяемым пользователем, но чаще тогда не it' s это. LPD хорош, поскольку существует маленький заголовок, который содержит информацию как целевая очередь, и т.д. сопровождаемая фактическими данными. Просто соберите некоторые данные, и Вы будете видеть, it' s довольно простой. – Douglas Anderson 19 February 2009 в 15:09
Другие вопросы по тегам:

Похожие вопросы: