Вопрос по linux, jvm, heap, java, memory – Java отказывается запускаться - не удалось зарезервировать достаточно места для кучи объектов

48
Background

У нас есть пул из примерно 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 не может начаться.

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

почему у вас 32b лезвия? :П wsorenson
+1 Хорошее количество деталей. xdhmoore
Привет, Рандя, ты в конце концов выяснил, что вызвало это? У меня точно такие же ошибки при попытке запустить сервер WebLogic ... Спасибо GavinWoods
К сожалению, нет, мы внедрили некоторые методы, чтобы уменьшить использование памяти и смогли снизить максимальную нагрузку до 1 гигабайта. Извини :( Randyaa

Ваш Ответ

15   ответов
15

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

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

2

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

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

Во-вторых, я сталкивался с тем, что вам может не хватать адресного пространства, звучит странно, я знаю. У него была проблема с запуском Glassfish с кучей 1,5 Гб, когда он пытался завершить JSP, мой разветвленный javac не удался, потому что ОС не могла выделить достаточно адресного пространства для вновь созданного процесса, даже если в коробке было 12 Гб памяти. Здесь может происходить нечто подобное.

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

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

Как я уже упоминал, если бы и у блоков SuSE, и у блоков RedHat была эта проблема, я бы с вами согласился. Они являются 32-битными ОС и имеют разные ограничения. Redhat, кажется, где-то около 2500+ МБ, тогда как коробки SuSE, кажется, где-то около 1850 МБ. Randyaa
Разные дистрибутивы могут иметь разные значения по умолчанию для пределов размера процесса. У них также разные версии ядра.
8

вы должны определенно обновить при первой возможности.

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

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

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

Я бы переключился, если бы мог. Это не мое дело. Мне нужно решить эту проблему, поэтому машины Redhat позволяют нам использовать 2500+ и почему ящики SuSE ограничивают нас до 1850. Randyaa
2

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

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

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

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

2

но если вы не можете выполнить обновление до Java 6, вы можете использовать последний патч 22-го уровня!

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

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

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

2

ошибку:

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

1

setSOADomainENV.cmd решил проблему.

REM set DEFAULT_MEM_ARGS=-Xms512m -Xmx1024m
set DEFAULT_MEM_ARGS=-Xms512m -Xmx768m
Добро пожаловать в ТАК. Вы уверены, что ответили на правильный вопрос?
21

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

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

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

Я уже упоминал, что я не думаю, что это имеет какое-либо отношение к нашей 32-битной ОС. Машины SuSE и RedHat являются 32-битными, и у них нет проблем. Что касается вашего предложения об установке минимума, я попробовал это, и он ничего не сделал для меня :(. Randyaa
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 ГБ, поэтому этот лимит не является проблемой?

1

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

sysctl -a

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

На вашем пути находится / sbin / sysctl? На самом деле, просто попробуйте запустить / sbin / sysctl -a.
команда не распознается на обоих типах машин. Randyaa
3

ограничений?

Улимит неограничен на обоих. Где бы я мог проверить ограничение виртуальной памяти? Randyaa
Используйте ulimit с ключом -a.ulimit -a
1

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

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

С наилучшими пожеланиями.

Oracle JRockit, в отличие от JVM от Sun и IBM, может использовать несмежную кучу. Это означает, что вы можете получить почти 3 ГБ в Windows, хотя не знаете, сколько вы можете получить в Linux. Смотрите этот блог для получения дополнительной информации;blogs.oracle.com/jrockit/2008/09/…
Я только что протестировал с клиентской виртуальной машиной Sun на Windows XP. Выше -Xmx1640M Я получаю ту же ошибку, что и вы: произошла ошибка во время инициализации виртуальной машины. Не удалось зарезервировать достаточно места для кучи объектов. Не удалось создать виртуальную машину Java. Я тестировал программу HelloWorld. Предел фиксируется JVM.
Мы просто используем JVM от Sun. Java-версия "1.5.0_10" Среда выполнения Java (TM) 2, Standard Edition (сборка 1.5.0_10-b03) Серверная виртуальная машина Java HotSpot (TM) (сборка 1.5.0_10-b03, смешанный режим) Randyaa
3

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

-3

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

2

которые начинаются с кучи размером 1024 м или 1280 м. Java ищет доступное пространство в разделе подкачки, и, если недостаточно памяти, jvm завершает работу.

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

Я работал на x86-64 Linux с 64-разрядной JVM.

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