Вопрос по linux, jvm, heap, java, memory – Java отказывается запускаться - не удалось зарезервировать достаточно места для кучи объектов
У нас есть пул из примерно 20 лезвий Linux. Некоторые используют Suse, некоторые используют Redhat. ВСЕ разделяют пространство NAS, которое содержит следующие 3 папки:
/NAS/app/java - a symlink that points to an installation of a Java JDK. Currently version 1.5.0_10 /NAS/app/lib - a symlink that points to a version of our application. /NAS/data - directory where our output is writtenВсе наши машины имеют 2 процессора (гиперпоточные) с 4 ГБ физической памяти и 4 ГБ пространства подкачки. Мы ограничиваем количество «рабочих мест»; каждая машина может обрабатывать в определенное время до 6 (это число, вероятно, нужно изменить, но это не входит в текущую проблему, поэтому, пожалуйста, пока игнорируйте ее).
Некоторые из наших заданий устанавливают максимальный размер кучи 512 МБ, некоторые другие резервируют максимальный размер кучи 2048 МБ. Опять же, мы понимаем, что можем перебрать доступную память, если на одном компьютере запущено 6 заданий с размером кучи 2048, но, насколько нам известно, этого еще не произошло.
The ProblemВремя от времени задание немедленно завершается неудачей со следующим сообщением:
Error occurred during initialization of VM
Could not reserve enough space for object heap
Could not create the Java virtual machine.
Мы привыкли записывать это на слишком много заданий, выполняемых одновременно на одной и той же машине. Проблема случалась достаточно редко (MAYBE один раз в месяц), что мы просто перезапустим его, и все будет хорошо.
Проблема в последнее время стала намного хуже. Все наши задания, которые запрашивают максимальный размер кучи 2048 м, сразу же почти каждый раз терпят неудачу, и перед выполнением их необходимо перезапустить несколько раз.
Мы вышли на отдельные машины и попытались выполнить их вручную с тем же результатом.
DebuggingОказывается, проблема существует только для наших коробок 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»; дает нам следующее на обоих типах машин:
UTC 2005 i686 i686 i386 GNU/Linux
На компьютере не выполняется никаких заданий, и никакие другие процессы не используют много памяти. Все процессы, запущенные в данный моментmight использовать 100 МБ всего.
& APOS; сверху & APOS; на данный момент показывает следующее:
Mem: 4146528k total, 3536360k used, 610168k free, 132136k buffers
Swap: 4194288k total, 0k used, 4194288k free, 3283908k cached
& APOS; vmstat & APOS; на данный момент показывает следующее:
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 не может начаться.
Любые объяснения будут с благодарностью.
проблема заключается в исчерпании виртуального адресного пространства. 32-битная пользовательская программа linux обычно ограничена 3 ГБ AS; оставшиеся 1 ГБ используются ядром (обоснование: поскольку верхний 1 ГБ является фиксированным ядром, отображая, что нет необходимости касаться таблицы страниц при обслуживании системных вызовов).
Однако в ядрах RHEL реализовано так называемое разделение на 4 ГБ / 4 ГБ, при котором полный процесс 4 ГБ доступен для процессов пользовательского пространства за счет небольших накладных расходов времени выполнения (ядро находится в отдельной виртуальной AS 4 ГБ)
но есть две вещи, которые приходят на ум. Оба следующих предположения предполагают, что вы используете 32-битную версию Linux.
В linux существует ограничение на размер процесса, кажется, помните, что в CentOS он составлял около 2,5 ГБ и настроен в ядре (то есть, для изменения). Ваш процесс может столкнуться с тем, что после добавления всего кода JVM + пространства Permgen и всех остальных библиотек JVM.
Во-вторых, я сталкивался с тем, что вам может не хватать адресного пространства, звучит странно, я знаю. У него была проблема с запуском Glassfish с кучей 1,5 Гб, когда он пытался завершить JSP, мой разветвленный javac не удался, потому что ОС не могла выделить достаточно адресного пространства для вновь созданного процесса, даже если в коробке было 12 Гб памяти. Здесь может происходить нечто подобное.
Я боюсь, что единственные решения для двух вышеперечисленных вариантов - это обновление до 64-битного ядра.
Надеюсь, что это полезно.
вы должны определенно обновить при первой возможности.
Я не знаю, требует ли Java, чтобы ее куча находилась в одном смежном куске, но если это так, запрос 1,8 Гб кучи для 32-битного блока звучит как высокий порядок. Вы предполагаете, что существует часть адресного пространства, почти половина которого свободна во время запуска JVM.
В зависимости от того, какие другие библиотеки загружены в то время, может не быть. Библиотеки могут выделять память где угодно, поэтому она может достаточно фрагментировать ваше адресное пространство, чтобы 1.8G не был доступен в одном блоке.
В любом случае, в 32-битном Linux доступно только около 3G адресного пространства. Для начала библиотеки и сама JVM используют некоторые из них.
Произошла ошибка при инициализации ВМ Не удалось зарезервировать достаточно места для кучи объектов Не удалось создать виртуальную машину Java.
Шаг 1: Уменьшите память, что раньше вы использовали .. java -Xms128m -Xmx512m -cp simple.jar
Шаг 2: Извлеките ОЗУ некоторое время из материнской платы, подключите ее и перезагрузите * может освободит память области кучи блокировки .. java -Xms512m -Xmx1024m -cp simple.jar
Надеюсь, теперь это будет хорошо работать ... :-)
но если вы не можете выполнить обновление до Java 6, вы можете использовать последний патч 22-го уровня!
Размер 32-битной Windows ограничен ~ 1,3 ГБ, поэтому вы можете выбрать максимум 1,8. Примечание: это проблема с непрерывной памятью, и поскольку ваша система работает, ее область памяти может быть фрагментирована, поэтому меня не удивит, что у вас есть эта проблема.
64-битная ОС не имеет этой проблемы, поскольку у нее гораздо больше виртуального пространства, вам даже не нужно обновлять ее до 64-битной версии Java, чтобы воспользоваться этим преимуществом.
Кстати, по моему опыту, 32-битная Java 5.0 может быть быстрее, чем 64-битная Java 5.0. Только через много лет Java 6 с обновлением 10 стал более быстрым для 64-битных систем.
ошибку:
$ 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 пытается получить память пропорционально доступной памяти, и терпит неудачу, если это не может.
поэтому из-за этого вы увидите ограничения на общий размер. Другие ответы охватили это более подробно, поэтому я не буду повторять их информацию.
Поведение, которое я недавно заметил на наших серверах, заключается в том, что указание максимального размера кучи с помощью-Xmx
не указывая минимальный размер кучи с-Xms
приведет к тому, что виртуальная машина Java-сервера немедленно попытается выделить всю память, необходимую для максимального размера кучи. И, конечно же, если приложение достигнет такого размера кучи, это количество памяти, которое вам понадобится. Но есть вероятность, что ваши приложения будут начинаться со сравнительно небольших куч иmay потребовать большую кучу в какой-то более поздний момент. Кроме того, указание минимального размера кучи позволит запустить ваше приложение с меньшей кучи и постепенно увеличивать ее.
Все это не поможет вам увеличить максимальный размер кучи, но я подумал, что это может помочь, так что ...
что для 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 ГБ, поэтому этот лимит не является проблемой?
что ни одно из других предложений не сработало (включая многие вещи, которые я сам предложил), чтобы помочь в дальнейшем устранении неполадок, не могли бы вы попробовать выполнить:
sysctl -a
На машинах SuSE и RedHat, чтобы увидеть, есть ли различия? Я предполагаю, что конфигурации по умолчанию отличаются между этими двумя дистрибутивами, которые вызывают это.
ограничений?
Я знаю, что BEA JRockit не превышает 1850 МБ для максимального размера кучи. Это не дает сбоя, но предупреждает пользователя, что он не будет использовать более 1850 МБ.
Я не знаю, почему существует такой предел, но я знаю, что он существует для BEA JRockit.
С наилучшими пожеланиями.
одно среднего размера, а другое довольно маленькое. Я зажигаю среднего размера (на Linux, Centos), без каких-либо аргументов, (Java-сервер), и это будет беги просто отлично. Но когда я запустил маленькое приложение с помощью «Java-клиента», оно сообщило бы я не мог зарезервировать достаточно места и не мог бежать. Я экспериментировал и использовал -Xms и -Xmx с 10 м, и они оба бежали бы без жалоб ... Иди разберись!
которые начинаются с кучи размером 1024 м или 1280 м. Java ищет доступное пространство в разделе подкачки, и, если недостаточно памяти, jvm завершает работу.
Чтобы решить эту проблему, мне пришлось закрыть несколько программ, у которых было выделено большое количество виртуальной памяти.
Я работал на x86-64 Linux с 64-разрядной JVM.