Java-приложение вызывает C ++ DLL через JNI;как лучше выделить память? - PullRequest
7 голосов
/ 09 октября 2011

Основная сводка вопроса: Как наилучшим образом оптимизировать распределение памяти, чтобы выделить как можно больше памяти для библиотек DLL, к которым у меня есть доступ через JNI? Что я должен стремиться минимизировать, что я должен стремиться к максимизации и т. Д.

СИСТЕМА: Запуск JBoss 6 в качестве службы Windows 32 в 32-разрядной системе с 4 ГБ ОЗУ. Я понимаю, что существуют максимальные ограничения на память для Java Heap. JVM составляет JRE1.6.0_26

SERVICE: Под JBoss установлено веб-приложение, которое получает запросы от клиентов; каждый запрос вызывает встроенную C ++ DLL через JNI для обработки файла образа тем или иным способом.

ВОПРОС: Иногда с большими или некоторыми (не всеми) изображениями со сжатием LZW вызывающий класс java получает сообщение о том, что DLL испытала глобальное истощение памяти и не смогла завершить запрошенный процесс.

На сервере больше ничего не работает, кроме основных процессов Windows.

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

-Xms1024m -Xmx1024m -Xss1024k -XX: MaxPermSize = 128 м

Я пытаюсь определить наилучшие настройки памяти, чтобы выделить столько ресурсов для JNI DLL, насколько я понимаю, JNI не использует память, выделенную для кучи Java.

Я прочитал их, но не нашел их полезными для ответа на мой вопрос:

Java JNI: выделение / разбиение памяти

Может ли jconsole использоваться для выявления утечек памяти в объектах JNI C ++?

Два предоставленных в настоящее время ответа не относятся к первому вопросу.

Текущая память сервера JBoss через одну неделю с параметрами JVM, установленными, как указано выше (TaskManager указывает процесс java.exe на 750 672 КБ)

Total Memory Pools: 5

Pool: Code Cache (Non-heap memory)

    Peak Usage : init:2359296, used:7317312, committed:7438336, max:50331648
    Current Usage : init:2359296, used:7306496, committed:7438336, max:50331648


        |---------| committed:7.09Mb
        +---------------------------------------------------------------------+
        |/////////| | max:48Mb
        +---------------------------------------------------------------------+
        |---------| used:6.97Mb


Pool: PS Eden Space (Heap memory)

    Peak Usage : init:268500992, used:354811904, committed:354811904, max:355991552
    Current Usage : init:268500992, used:270153472, committed:354091008, max:354156544


        |--------------------------------------------------------------------| committed:337.69Mb
        +---------------------------------------------------------------------+
        |///////////////////////////////////////////////////// || max:337.75Mb
        +---------------------------------------------------------------------+
        |----------------------------------------------------| used:257.64Mb


Pool: PS Survivor Space (Heap memory)

    Peak Usage : init:44695552, used:44694896, committed:78643200, max:78643200
    Current Usage : init:44695552, used:0, committed:1835008, max:1835008


        |---------------------------------------------------------------------| committed:1.75Mb
        +---------------------------------------------------------------------+
        | | max:1.75Mb
        +---------------------------------------------------------------------+
        | used:0b


Pool: PS Old Gen (Heap memory)

    Peak Usage : init:715849728, used:123671968, committed:715849728, max:715849728
    Current Usage : init:715849728, used:104048648, committed:715849728, max:715849728


        |---------------------------------------------------------------------| committed:682.69Mb
        +---------------------------------------------------------------------+
        |////////// | max:682.69Mb
        +---------------------------------------------------------------------+
        |---------| used:99.23Mb


Pool: PS Perm Gen (Non-heap memory)

    Peak Usage : init:16777216, used:91989664, committed:134217728, max:134217728
    Current Usage : init:16777216, used:90956472, committed:90963968, max:134217728


        |----------------------------------------------| committed:86.75Mb
        +---------------------------------------------------------------------+
        |//////////////////////////////////////////////| | max:128Mb
        +---------------------------------------------------------------------+
        |----------------------------------------------| used:86.74Mb

1 Ответ

11 голосов
/ 24 октября 2011

Память, выделенная собственным кодом, обернутым JNI, выделяется процессу JVM, но не находится под контролем вашего кода Java.Он не является частью кучи и не настраивается с помощью параметров JVM.По сути, все, что выделено с помощью собственного malloc, должно управляться этим собственным кодом.Если вы контролируете библиотеки, которые используете, обязательно просмотрите их и проверьте на утечки ресурсов.Это особенно важно, если это используется в долгоживущем процессе.

По моему опыту, наилучшим подходом было бы проверить фактическое использование памяти, извлекая статистику JMX, предоставляемую JVM.Как только вы поймете, сколько памяти занимает ваше Java-приложение, у вас будет лучшее представление о том, где устанавливать максимальные параметры кучи.Пермгенское пространство используется для определений классов и тому подобного, поэтому вам действительно не нужно много памяти, если вы не выполняете кучу динамической загрузки классов.

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

Как и следовало ожидать, при сложении пиков кучи памяти вместе получается примерно 1022,19 (максимальный размер вашей кучи),Когда куча исчерпана, запускается полный прогон GC и восстанавливается грязная куча.Исходя из предоставленных вами цифр, я бы предложил начать с Xmx512m.Это даст вашему коду JNI комнату для дыхания.

Если вы обнаружите, что JVM работает из-за чрезмерной сборки мусора, а это означает, что у вас слишком быстро заканчивается куча Java, вы можете увеличить это распределение.Однако, если он потребляет 512 МБ достаточно быстро, чтобы вызвать заметное снижение производительности, маловероятно, что что-либо, кроме значительного увеличения, будет иметь большой эффект.Все это сильно зависит от вашей программы, от того, насколько быстро она съедает кучу Java, и от того, насколько эффективен полный запуск GC.

...