Java отказывается запускаться - не удалось зарезервировать достаточно места для кучи объектов - PullRequest
48 голосов
/ 29 июня 2009

Фон

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

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

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

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

Проблема

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

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

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

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

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

Debugging

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

'cat / proc / version' на полях SuSE дает нам:

Linux version 2.6.5-7.244-bigsmp (geeko@buildhost) (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 (bhcompile@bugs.build.redhat.com) (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' дает нам следующее для ОБА типов машин:

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.

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

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

Ответы [ 15 ]

21 голосов
/ 29 июня 2009

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

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

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

15 голосов
/ 06 ноября 2009

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

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

8 голосов
/ 30 июня 2009

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

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

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

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

4 голосов
/ 29 июня 2009

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

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

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

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

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

3 голосов
/ 05 октября 2012

Я написал два приложения, одно среднего размера, а другое довольно маленькое. Я бы выстрелил среднего размера (на Linux, Centos), без каких-либо аргументов, (Java-сервер), и это будет беги просто отлично. Но когда я запустил маленькое приложение с помощью «Java-клиента», оно сообщило бы я не смог бы зарезервировать достаточно места и не побежал бы. Я экспериментировал и использовал -Xms и -Xmx с 10 м, и они оба бежали бы без жалоб ... Иди к черту!

3 голосов
/ 29 июня 2009

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

2 голосов
/ 13 февраля 2013

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

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

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

2 голосов
/ 24 ноября 2011

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

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

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

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

2 голосов
/ 22 декабря 2010

Я обновил память машины с 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 пытается получить память пропорционально доступной памяти, и терпит неудачу, если не может.

2 голосов
/ 14 мая 2010

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

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

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

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

...