Java отказывается запускать - не удалось зарезервировать достаточно места для кучи объекта

Фон

У нас есть пул примерно 20 linux-дисков. Некоторые из них запускают Suse, некоторые работают с Redhat. ВСЕ разделяют пространство NAS, которое содержит следующие 3 папки:

  • /NAS/app/java - символическая ссылка, которая указывает на установку Java JDK. В настоящее время версия 1.5.0_10
  • /NAS/app/lib - символическая ссылка, указывающая на версию нашего приложения.
  • /NAS/data - каталог, в котором написан наш вывод

Все наши машины имеют 2 процессора (hyperthreaded) с 4 ГБ физической памяти и 4 ГБ пространства подкачки. Мы ограничиваем количество "заданий", которые каждая машина может обрабатывать в данный момент времени до 6 (это число, вероятно, должно измениться, но это не входит в текущую проблему, поэтому пока игнорируйте его).

Некоторые из наших заданий задают размер Max Heap размером 512 МБ, некоторые другие резервируют размер Max Heap размером 2048 МБ. Опять же, мы понимаем, что мы можем перейти к нашей доступной памяти, если на той же машине началось 6 заданий с размером кучи, установленным на 2048, но, насколько нам известно, этого еще не произошло.

Проблема

Время от времени задание будет немедленно сбой со следующим сообщением:

Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

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

Проблема в последнее время значительно ухудшилась. Все наши задания, которые запрашивают максимальный размер кучи 2048 м, немедленно срабатывают почти каждый раз и должны быть перезагружены несколько раз до завершения.

Мы отправились на отдельные машины и попытались выполнить их вручную с тем же результатом.

Отладка

Оказывается, проблема существует только для наших ящиков SuSE. Причина, по которой это происходит чаще, состоит в том, что мы добавляем больше машин, а новые - SuSE.

'cat/proc/version' в окне SuSE:

Linux version 2.6.5-7.244-bigsmp ([email protected]) (gcc version 3.3.3 (SuSE Linux)) #1 SMP Mon Dec 12 18:32:25 UTC 2005

'cat/proc/version' в блоках RedHat дайте нам:

Linux version 2.4.21-32.0.1.ELsmp ([email protected]) (gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-52)) #1 SMP Tue May 17 17:52:23 EDT 2005

'uname -a' дает нам следующие типы BOTH машин:

UTC 2005 i686 i686 i386 GNU/Linux

На компьютере нет заданий, и никакие другие процессы не используют много памяти. Все запущенные процессы могут использовать 100 мб.

'top' в настоящее время показывает следующее:

Mem:   4146528k total,  3536360k used,   610168k free,   132136k buffers
Swap:  4194288k total,        0k used,  4194288k free,  3283908k cached

'vmstat' в настоящее время показывает следующее:

procs -----------memory---------- ---swap-- -----io---- --system-- ----cpu----
r  b   swpd   free   buff  cache   si   so    bi    bo   in    cs us sy id wa
0  0      0 610292 132136 3283908    0    0     0     2   26    15  0  0 100  0

Если мы запускаем задание со следующей командной строкой (Max Heap 1850mb), он начинает нормально:

java/bin/java -Xmx1850M -cp helloworld.jar HelloWorld
Hello World

Если мы увеличиваем максимальный размер кучи до 1875 мб, он терпит неудачу:

java/bin/java -Xmx1875M -cp helloworld.jar HelloWorld
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Совершенно ясно, что используемая память используется для буферизации/кэширования и поэтому так мало отображается как "свободный". Неясно, почему существует магическая линия 1850mb, где что-то более высокое означает, что Java не может запускаться.

Любые объяснения будут с благодарностью.

Ответ 1

Вы используете 32-битную ОС, поэтому из-за этого вы будете видеть ограничения на общий размер. Другие ответы затронули это более подробно, поэтому я не буду повторять их информацию.

Поведение, которое я недавно заметил с нашими серверами, заключается в том, что указание максимального размера кучи с -Xmx, а не указание минимального размера кучи с помощью -Xms приведет к тому, что виртуальная машина Java Java немедленно попытается выделить всю память, необходимую для максимальный размер кучи. И конечно, если приложение встанет на этот размер кучи, то объем памяти, который вам понадобится. Но, скорее всего, ваши приложения будут начинаться со сравнительно небольшой кучи и могут потребовать большую кучу в какой-то более поздний момент. Кроме того, указав минимальный размер кучи, вы можете начать свое приложение с меньшей кучи и постепенно увеличивать эту кучу.

Все это не поможет вам увеличить максимальный размер кучи, но я решил, что это может помочь, поэтому...

Ответ 2

Как было предложено в других ответах, проблема связана с исчерпанием виртуального адресного пространства. 32-битная пользовательская программа Linux обычно ограничена 3 ГБ AS; оставшаяся 1 ГБ используется ядром (логическое обоснование: поскольку верхняя 1 ГБ - фиксированное отображение ядра, не нужно касаться таблицы страниц при обслуживании системных вызовов).

Ядра RHEL, однако, реализуют так называемый раздел 4 ГБ /4 ГБ, где полный 4 ГБ AS доступен для процессов пользовательского пространства с небольшими затратами времени выполнения (ядро живет в отдельной виртуальной AS 4 ГБ)

Ответ 3

Запуск 32-разрядной ОС - ошибка; вы должны обязательно обновить их как можно скорее.

Я не знаю, требует ли Java свою кучу в одном непрерывном куске, но если это так, запрос 1.8G кучи на 32-битном поле звучит как высокий порядок. Вы предполагаете, что в момент запуска JVM есть кусок адресного пространства, почти половина его, бесплатно.

В зависимости от того, какие другие библиотеки загружаются в то время, может не быть. Библиотеки могут выделять память в любом месте, чтобы они могли фрагментировать ваше адресное пространство в достаточной степени, чтобы 1.8G не было доступно в одном фрагменте.

В любом случае на 32-разрядной версии Linux всего лишь 3-х адресное пространство 3G. Библиотеки и JVM сами используют некоторые для начала.

Ответ 4

Кажется, что для 32-битных серверов существует ограничение JVM, которое невозможно преодолеть (если вы не найдете специальную 32-разрядную JVM, которая не налагает ограничение 2 ГБ или меньше).

В этой ветке на стороне сервера есть более подробная информация, включая несколько человек, которые тестировали различные JVM на 32-разрядных архитектурах. IBM JVM, похоже, позволяет еще 100 МБ, но на самом деле это не поможет вам получить то, что вы хотите.

http://www.theserverside.com/discussions/thread.tss?thread_id=26347

"Реальное" решение - использовать 64-разрядный сервер с 64-разрядной JVM, чтобы получить кучи размером более 2 ГБ на каждый процесс. Тем не менее, важно также учитывать влияние увеличения размера вашего адреса (а не только адресного пространства) с помощью 64-битной JVM. Вероятно, производительность и память повлияют на обработку с использованием менее 4 ГБ памяти.

Пища для размышлений: действительно ли каждая из этих заданий требует 2 ГБ памяти? Есть ли способ изменения заданий для работы в пределах 1,8 ГБ, поэтому этот предел не является проблемой?

Ответ 5

Максимальный объем памяти ulimit и виртуальная память установлены неограниченно?

Ответ 6

Я написал два приложения: один средний и другой, довольно маленький. Я запустил бы средний размер (на linux, centos), без каких-либо аргументов (java-сервер), и это бежать просто отлично. Но когда я затем активировал меньшее приложение с помощью "java-клиента", он сказал бы я не мог зарезервировать достаточно места и не побежал. Я экспериментировал и использовал -Xms и -Xmx как с 10 м, так и они оба бежали без жалобы... Иди цифру!

Ответ 7

Это может быть выход из трека, но есть две вещи, которые spring. Оба из них предполагают, что вы используете 32-битную версию Linux.

В Linux существует ограничение размера процесса, похоже, что на CentOS было около 2,5 гб и настроено в ядре (т.е. рекомплекс для изменения). Ваш процесс может быть поражен, когда вы добавите все JVM-код + пространство Permgen и все остальные библиотеки JVM.

Во-вторых, я столкнулся с тем, что у вас может быть нехватка адресного пространства, и я знаю, что это звучит. Если у вас возникла проблема с Glassfish с кучей 1.5Gb, когда он попытался выполнить JSP, то это будет неудачно, потому что ОС не сможет выделить достаточно адресного пространства для вновь созданного процесса, даже если в коробке было 12 ГБ памяти. Здесь может быть что-то похожее.

Я боюсь единственных решений для двух вышеперечисленных, где можно перейти на 64-битное ядро.

Надеюсь, это будет полезно.

Ответ 8

Вам нужно посмотреть на обновление ОС и Java. Java 5.0 - EOL, но если вы не можете обновить Java 6, вы можете использовать последний уровень исправления 22!

32-разрядная версия Windows ограничена ~ 1,3 ГБ, так что вы преуспеваете в максимуме до 1,8. Примечание. Это проблема с постоянной памятью, и по мере того, как ваша система запускает свою память, ее фрагмент может быть фрагментирован, поэтому он не удивляет меня, что у вас есть эта проблема.

64-разрядная ОС не имеет этой проблемы, так как у нее гораздо больше виртуального пространства, вам даже не нужно обновлять до 64-разрядной версии Java, чтобы воспользоваться этим.

BTW, по моему опыту, 32-разрядная версия Java 5.0 может быть быстрее, чем 64-разрядная версия Java 5.0. Только спустя много лет, обновление Java 6 10 было быстрее для 64-разрядных версий.

Ответ 9

Я обновил память машины от 2 ГБ до 4 ГБ и сразу же получил ошибку:

$ java -version
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.

Проблема заключалась в ulimit, который я установил в 1 ГБ для адресного пространства. Увеличение его до 2 ГБ решило проблему.

-Xms и -Xmx не имели эффекта.

Похоже, java пытается получить память пропорционально доступной памяти и терпит неудачу, если она не может.

Ответ 10

Шаги для выполнения.... для решения проблемы Ошибка при инициализации виртуальной машины Не удалось зарезервировать достаточно места для кучи объектов Не удалось создать виртуальную машину Java.

Шаг 1: Уменьшите память, что раньше вы использовали. java -Xms128m -Xmx512m -cp simple.jar

Шаг 2: Удалите оперативную память некоторое время с материнской платы и подключите ее и перезапустите * может ли он освободить память области кучи памяти. java -Xms512m -Xmx1024m -cp simple.jar

Надеюсь, что теперь это будет хорошо работать...: -)

Ответ 11

Недавно я столкнулся с этой проблемой. У меня есть 3 java-приложения, которые начинаются с размера кучи 1024 или 1280 м. Java просматривает доступное пространство в swap, и если доступной памяти недостаточно, jvm завершает работу.

Чтобы решить эту проблему, мне пришлось закончить несколько программ, на которых было выделено большое количество виртуальной памяти.

Я работал на x86-64 linux с 64-битным jvm.

Ответ 12

Что такое JVM? Я знаю, что BEA JRockit не превышает 1850 мБ для максимального размера кучи. Он не прерывается, но предупреждает пользователя о том, что он не будет использовать более 1850 мБ.

Я не знаю, почему существует такой предел, но я знаю, что он существует для BEA JRockit.

С уважением.

Ответ 13

Учитывая, что ни одно из других предложений не сработало (включая многие вещи, которые я бы предложил сам), чтобы помочь устранить неполадку, не могли бы вы попробовать запустить:

sysctl -a

Как на машинах SuSE, так и на RedHat, чтобы увидеть, есть ли какие-либо различия? Я предполагаю, что конфигурации по умолчанию различаются между этими двумя дистрибутивами, которые вызывают это.

Ответ 14

Я использую SOA env, Уменьшенный Xmx от 1024 до 768 в setSOADomainENV.cmd решил проблему.

REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m
set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m

Ответ 15

В Windows я решил эту проблему непосредственно редактировать файл /bin/cassandra.bat, изменив значение параметров "Xms" и "Xmx" JVM_OPTS. Вы можете попробовать отредактировать файл /bin/cassandra. В этом файле я вижу прокомментированную переменную JVM_OPTS, пытаюсь раскомментировать и отредактировать ее.