Java: Все процессы работают под одной и той же JVM? - PullRequest
3 голосов
/ 15 января 2010

У нас есть сервер Linux, который запускает около 20 Java-программ. Все эти Java-программы идентичны, за исключением того, что они используют другой порт. Эти программы работают нормально. Однако через некоторое время все 20 программ вылетают в одно и то же время. Каждой из этих программ выделяется 2 гигабайта памяти, при запуске их так:

java -jar -Xmx 2000м

Однако, насколько нам известно, эти программы не подходят близко к использованию такого количества памяти. Вся система имеет 4 гигабайта памяти.

ТАК, вопрос в том, может ли java-программа отвечать за сбой всех 9 других? Разделяется ли виртуальная машина, чтобы при ее сбое ВСЕ Java-программы зависали? Есть ли файл журнала, который я мог бы проверить по причине, почему Java потерпел крах? В выводе java не было ошибок.

EDIT: Странно то, что это произошло через более длительное время, например, 3 часа. Эти 20 процессов работали в течение достаточно долгого времени, прежде чем внезапно ВСЕ произошли сбои одновременно. И почему они ВСЕ терпят крах, если среда выполнения Java запускает свой собственный процесс для каждой программы?

Ответы [ 7 ]

7 голосов
/ 15 января 2010

Трудно точно сказать, почему все процессы Java завершаются в одно и то же время. Даже не понятно, почему они умирают. Чтобы диагностировать эти проблемы, я бы:

  • включить ведение журнала GC; например добавить параметр командной строки "-verbose: gc",

  • убедитесь, что приложение перехватывает и регистрирует исключения, которые могут убить «главный» поток, и

  • посмотрите в текущем каталоге процессов, чтобы увидеть, не покидают ли они аварийные дампы.

Но независимо от этого, когда вы запускаете java -jar -Xmx2000m ... 20 раз, вы запускаете 20 процессов ОС, каждый из которых может использовать более 2 ГБ виртуальной памяти. На машине с 4 Гб физической памяти это просто безумие. Даже если у вас достаточно пространства подкачки (40 ГБ или более) для поддержки такого большого количества виртуальной памяти, есть вероятность, что вы вызовете перегрузку виртуальной памяти до того, как куча станет такой большой. Когда система начинает работать, производительность системы падает до минимума.

Чтобы избежать этого, вам нужно убедиться, что общие виртуальные требования всех активных процессов в системе не намного больше, чем у вашей физической памяти. Уменьшите количество процессов Java, уменьшите их максимальные размеры кучи или оба. (И имейте в виду, что JVM также использует память без кучи.)

Еще одна вещь, которую вы должны рассмотреть, - это перестроить вашу систему так, чтобы она использовала многопоточность внутри одной JVM, а не с использованием нескольких JVM. При правильной реализации вы сможете увеличить пропускную способность в многопоточной архитектуре, поскольку:

  • это позволяет избежать нескольких копий кода и общих структур данных, поэтому у вас относительно больше памяти для полезных объектов кучи,

  • потоки в многопоточной архитектуре могут совместно использовать кэши ранее выбранных объектов, ранее вычисленных значений и т. Д. И

  • GC более эффективен с одной большой кучей, чем множество маленьких куч,

5 голосов
/ 15 января 2010

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

3 голосов
/ 15 января 2010

Нет - java.exe запускает новую среду выполнения. Таким образом, если вы выполните его 20 раз, у вас будет запущено 20 JVM, каждому из которых разрешено до 2 ГБ памяти. Поскольку у вас всего 4 ГБ, вполне возможно, что вам не хватает памяти, просто пытаясь выделить слишком много.

1 голос
/ 15 января 2010

Обратите внимание, что запуск JVM от Sun с -Xmx2000m ограничивает кучу до 2 ГБ. Есть и другие области памяти, которые должны быть независимо измерены.

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

Существуют JVM, отличные от Sun, которые допускают разные параметры размеров памяти; возможно, вы бы предпочли альтернативную JVM.

Различные Java-программы регистрируют свои выходные данные по-разному, поэтому на самом деле невозможно определить, где находится журнал, не имея дополнительных знаний о программе.

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

1 голос
/ 15 января 2010

Каждая Java-программа будет иметь свой собственный процесс. Код в памяти будет разделен (то есть двоичные файлы ВМ), но это не должно быть проблемой.

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

Может случиться так, что весь процесс запрашивает 2G, в общей сложности 40G памяти, а ОС просто позволяет это. Если процессы ведут себя одинаково и продолжают увеличиваться в объеме памяти, в какой-то момент они достигнут размера 200 М (я не обращаю внимания на другие процессы и все такое, только для упрощения чисел), а попытка использовать больше памяти убьет процесс с ошибкой сегментации.

Теперь я не ожидал, что это уничтожит все ваши приложения сразу, так как после того, как первое приложение будет убито, память будет восстановлена ​​ОС, и она будет доступна для других процессов, и поэтому они будут умирать один по крайней мере 1 или 2 должны быть живы в конце. В некоторых редких случаях может случиться так, что хотя первый процесс все еще очищается после (сбрасывается ядро ​​и все остальное, что связано с ОС ...), остальные процессы сталкиваются с одной и той же проблемой, и все они умирают раньше память из первого действительно доступна ... но я бы не рассчитывал на это как на событие с высокой вероятностью.

0 голосов
/ 15 января 2010

Похоже на работу страшного Linux OOM Killer (нет, это не шутка). как уже упоминали другие, вы, вероятно, перераспределяете память на коробке, а убийца OOM стремится к целевым процессам с большой резидентной памятью (например, jvm).

0 голосов
/ 15 января 2010

java -Xmx определяет только максимальный размер кучи. Чтобы заставить их сразу же получить 2 ГБ, вам нужно использовать -Xms . Оба законны вместе, то есть java.-Xmx2000m -Xms2000m. Для получения более подробной информации наберите «java -X».

Если у вас jvm не хватает памяти, они должны сообщить о нехватке памяти. Запустите их для вывода в журнал. Вы также можете настроить их на запуск дампа кучи , когда они умрут, поскольку, вероятно, здесь происходит что-то еще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...