32-битная JVM передает> 3G виртуальную память - PullRequest
1 голос
/ 31 октября 2011

у нас есть 32-битная JVM, работающая под 64-битным RHEL5 на коробке, которая имеет много памяти (32G). По разным причинам этот процесс требует довольно большой управляемой кучи и пространства permgen - в настоящее время он работает со следующими аргументами VM:

-Xmx2200M -XX: MaxPermSize = 128M -XX: + CMSClassUnloadingEnabled

Я недавно начал видеть сбой JVM, потому что он - казалось бы - исчерпал собственную память (он не мог создавать собственные потоки или не мог выделить собственную память и т. Д.). Эти сбои не были (напрямую) связаны с состоянием управляемой кучи, так как при возникновении этих сбоев управляемая куча была заполнена на ~ 50-70%. Я знаю, что память, зарезервированная для управляемого процесса, близка к 2,5 ГБ, что оставляет не более 0,5 Г для самой JVM, НО - Я не понимаю, почему 0,5 недостаточно для JVM, даже если происходит постоянная GCing - настоящий вопрос заключается в следующем: когда я подключаюсь к процессу с помощью jconsole, он говорит, что (в настоящее время)

Committed virtual memory: 
3,211,180 kbytes

Что больше, чем 3G. Я могу представить, что по какой-то причине JVM считает, что 3,211,180 килобайт (3,06 ГБ) памяти, но когда он пытается перейти через 3G, распределение памяти не удается.

Любые идеи по а) почему это происходит б) как можно этого избежать

Спасибо. Mate

Ответы [ 2 ]

3 голосов
/ 31 октября 2011

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

Вы должны избегать необходимости в большом количестве памяти в 32-битном процессе. Это фундаментальная проблема. Получить 64-битную виртуальную машину, которая позволит вам использовать гораздо больше памяти, чем было бы в противном случае, - тривиально. В этой ситуации ее просто можно использовать.

Если вы используете 32-битный процесс, существует высокая вероятность того, что вы столкнулись с пределом эффективного адресного пространства 32-битного процесса. Для окон это максимум около 3 ГБ - все, что выше, зарезервировано для пространства ввода-вывода и ядра. Вы можете переместить это, но он имеет тенденцию ломать приложения / драйверы, предназначенные для 32-битной ОС.

В Linux у вас получается ~ 3 ГБ доступной адресуемой оперативной памяти на процесс, остальное используется такими вещами, как ядро, и отображается в общих библиотеках. Этот предел называется «пределом адресного пространства», и я предполагаю, что его можно настроить.

Как этого избежать? Ну, по большей части, вы не можете, это физическое ограничение 32-битного адресного пространства и необходимость наличия ядра / ввода-вывода в том же адресном пространстве, что и процесс для 32-битной ОС.

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

0 голосов
/ 31 октября 2011

Когда вы запускаете JVM, он сразу выделяет максимальный размер. Сколько из этой памяти используется, на самом деле не имеет значения. Ваше приложение может адресовать около 3 ГБ, из которых около 2,3 ГБ вы выделили для кучи и перманента. Остальное доступно для общих библиотек (обычно около 200 МБ) и стеков потоков.

Беспокоиться о том, почему вы не можете использовать полные 3 ГБ адреса, не очень полезно, когда решение относительно тривиально (используйте 64-битную JVM) доступно в 32-битной версии. Однако, если у вас есть дополнительные общие библиотеки, они могут легко использовать сотни МБ.

...