Подтвердить что ты не робот

Использование памяти Java в Linux

Я запускаю несколько серверов приложений Java, на которых работают последние версии Tomcat 6 и Sun Java 6 поверх CentOS 5.5 Linux. Каждый сервер запускает несколько экземпляров Tomcat.

Я устанавливаю параметры -Xmx450m -XX: MaxPermSize = 192m, чтобы контролировать, насколько увеличится куча и пермг. Эти настройки применяются ко всем экземплярам Tomcat на всех серверах приложений Java, всего около 70 экземпляров Tomcat.

Вот типичное использование памяти одного из этих экземпляров Tomcat, как описано Psi-probe

Eden           = 13M
Survivor       = 1.5M 
Perm Gen       = 122M 
Code Cache     = 19M 
Old Gen        = 390M 
Total          = 537M

Однако CentOS сообщает об использовании ОЗУ для этого конкретного процесса на 707M (согласно RSS), который оставляет 170M RAM без учета.

Я знаю, что сам JVM и некоторые из его библиотек зависимостей должны быть загружены в память, поэтому я решил запустить pmap -d, чтобы узнать их объем памяти. По моим расчетам, на которые приходится около 17 млн.

Далее существует стек потоков Java, который составляет 320 тыс. на поток в 32-разрядной JVM для Linux. Опять же, я использую Psi-probe для подсчета количества потоков в этой конкретной JVM, а общее число - 129 потоков. Итак, 129 + 320k = 42M

Я читал, что NIO использует память за пределами кучи, но мы не используем NIO в наших приложениях.

Итак, здесь я вычислил все, что приходит (мой) ум. И я только учёл 60 миллионов "отсутствующих" 170M.

Что мне не хватает?

4b9b3361

Ответ 1

Попробуйте использовать инкрементный сборщик мусора, используя опцию командной строки -Xincgc. Это немного более агрессивно для всех усилий GC, и у него есть особая счастливая небольшая аномалия: он фактически возвращает часть своей неиспользуемой памяти в ОС, в отличие от настроек по умолчанию и других GC! Это заставляет JVM потреблять намного меньше памяти, что особенно хорошо, если вы используете несколько JVM на одной машине. За счет некоторой производительности - но вы можете этого не заметить. Кажется, что incgc немного секрет, потому что никто никогда его не поднимал... Он был там на протяжении эонов (90 даже).

Ответ 2

Arnar. В процессе инициализации JVM JVM будет выделять память (mmap или malloc) размера, заданного -Xmx и MaxPermSize, поэтому в любом случае JVM будет выделять 450 + 192 = 642 м кучи пространства для приложения в начале процесса JVM, Таким образом, пространство кучи java для приложения не 537, а его 642 м. Итак, теперь, если вы сделаете расчет, он даст вам недостающую память. Надеюсь, это поможет.

Ответ 3

Java выделяет столько виртуальной памяти, сколько может потребоваться, но резидентная сторона будет именно той, которую вы на самом деле используете. Примечание. Многие библиотеки и потоки имеют свои собственные головки, и, хотя вы не используете прямую память, это не означает, что ни одна из базовых систем не делает. например если вы используете NIO, он будет использовать некоторую прямую память, даже если вы используете кучу ByteBuffers.

Наконец, 100 МБ стоит около £ 8. Возможно, это не стоит тратить слишком много времени на беспокойство об этом.

Ответ 5

Arnar, JVM также mmap все используемые jar файлы, которые будут использовать NIO и будут вносить вклад в RSS. Я не считаю, что эти данные учтены в любом из ваших измерений выше. У вас случайно есть значительное количество больших файлов jar? Если это так, страницы, используемые для них, могут быть вашей отсутствующей памятью.