Что работает в куче C по сравнению с кучей Java в среде JVM HP-UX?

Я столкнулся со своеобразной проблемой с некоторыми приложениями Java в среде HP-UX.

Для кучи задано значение -mx512, но, глядя на области памяти для этого процесса Java с помощью gpm, он показывает, что он использует более 1,6 ГБ памяти RSS, из которых 1,1 ГБ выделено для области DATA. Растет довольно быстро в течение 24-48 часов, а затем существенно замедляется, по-прежнему увеличиваясь на 2 МБ каждые несколько часов. Однако в куче Java нет признаков утечки.

Любопытно, как это было возможно, я немного исследовал и нашел эту статью HP об утечках памяти в куче java и куче c: http://docs.hp.com/en/JAVAPERFTUNE/Memory-Management.pdf

Мой вопрос заключается в том, что определяет, что выполняется в куче C по сравнению с кучей java, и для вещей, которые не выполняются в куче java, как бы вы определили эти объекты, запущенные в куче C? Кроме того, находится ли куча java внутри кучи C?


person zxcv    schedule 16.09.2008    source источник


Ответы (3)


Рассмотрим, что составляет процесс Java.

У тебя есть:

  • JVM (программа на C)
  • Данные JNI
  • Байт-коды Java
  • Java-данные

Примечательно, что ВСЕ они живут в куче C (куча JVM, естественно, является частью кучи C).

В куче Java находятся просто байт-коды Java и данные Java. Но то, что также находится в куче Java, — это «свободное пространство».

Типичная (например, Sun) JVM только увеличивает свою кучу Java по мере необходимости, но никогда не сжимает ее. Как только он достигает заданного максимума (-Xmx512M), он перестает расти и обрабатывает все, что осталось. Когда эта максимальная куча исчерпана, вы получаете исключение OutOfMemory.

Что эта опция Xmx512M НЕ делает, так это ограничивает общий размер процесса. Он ограничивает только часть процесса Java Heap.

Например, у вас может быть надуманная программа на Java, которая использует 10 МБ кучи Java, но вызывает вызов JNI, который выделяет 500 МБ кучи C. Вы можете видеть, насколько велик размер вашего процесса, хотя куча Java мала. Кроме того, с новыми библиотеками NIO вы также можете подключать память за пределами кучи.

Другой аспект, который вы должны учитывать, заключается в том, что Java GC обычно является "копирующим сборщиком". Это означает, что он берет «живые» данные из памяти, которую собирает, и копирует их в другой раздел памяти. Это пустое пространство, которое копируется в НЕ ЯВЛЯЕТСЯ ЧАСТЬЮ КУЧИ, по крайней мере, не с точки зрения параметра Xmx. Это что-то вроде «новой кучи», которая становится частью кучи после копирования (старое пространство используется для следующего GC). Если у вас есть куча размером 512 МБ, а она составляет 510 МБ, Java скопирует куда-то живые данные. Наивной мыслью было бы другое большое открытое пространство (например, 500+ МБ). Если бы все ваши данные были «живыми», то для копирования понадобился бы такой большой фрагмент.

Итак, вы можете видеть, что в самом крайнем случае вам потребуется как минимум вдвое больше свободной памяти в вашей системе для обработки кучи определенного размера. Не менее 1 ГБ для кучи размером 512 МБ.

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

Наконец, обратите внимание, что JVM делает забавные вещи, такие как сопоставление классов rt.jar с виртуальной машиной для облегчения запуска. Они отображаются в блоке только для чтения и могут совместно использоваться другими процессами Java. Эти общие страницы будут «засчитываться» для всех процессов Java, хотя на самом деле они потребляют физическую память только один раз (магия виртуальной памяти).

Теперь о том, почему ваш процесс продолжает расти, если вы никогда не сталкиваетесь с сообщением Java OOM, это означает, что ваша утечка НЕ ​​находится в куче Java, но это не значит, что она не может быть в чем-то другом (среда выполнения JRE, сторонняя библиотека JNI, собственный драйвер JDBC и т. д.).

person Will Hartung    schedule 17.09.2008

Как правило, в куче Java хранятся только данные в объектах Java, вся остальная память, необходимая виртуальной машине Java, выделяется из «собственной» или «C» кучи (фактически сама куча Java — это всего лишь один непрерывный фрагмент, выделенный из кучи С).

Поскольку для JVM требуется, чтобы куча Java (или кучи, если используется сборщик мусора поколений) была непрерывной частью памяти, весь максимальный размер кучи (значение -mx) обычно выделяется во время запуска JVM. На практике виртуальная машина Java будет пытаться свести к минимуму использование этого пространства, чтобы операционной системе не нужно было резервировать для нее какую-либо реальную память (ОС достаточно хитра, чтобы знать, когда часть хранилища никогда не записывалась). .

Таким образом, куча Java будет занимать определенный объем памяти.

Остальная часть хранилища будет использоваться виртуальной машиной Java и любым используемым кодом JNI. Например, JVM требует памяти для хранения байт-кода Java и пулов констант из загруженных классов, результата скомпилированного JIT-кода, рабочих областей для компиляции JIT-кода, собственных стеков потоков и других подобных мелочей.

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

person Mike Tunnicliffe    schedule 17.09.2008

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

Java от Sun еще не открыта на 100%, они работают над этим, но я полагаю, что в sourceforge есть такая возможность.

Java кстати тоже жрет память. Иногда это немного сбивает с толку управление памятью ОС (вы видите это, когда Windows исчерпывает память и просит Java освободить часть, Java трогает все свои объекты, заставляя их загружаться из файла подкачки, Windows кричит в агонии и умирает), но Я не думаю, что это то, что вы видите.

person Bill K    schedule 16.09.2008