Приложение, которое мы недавно начали спорадически сбой, с сообщением о «java.lang.OutOfMemoryError: запрошено 8589934608 байт для Chunk :: new. Из области подкачки?».Java JIT-компилятор, вызывающий OutOfMemoryError
Я посмотрел вокруг на сети, и везде предложения ограничиваются
- вернуться к предыдущей версии Java
- скрипки с настройками памяти
- использование клиента вместо режима сервера
Возвращение к предыдущей версии подразумевает, что у новой Java есть ошибка, но я не видел никаких указаний на это. Память не является проблемой вообще; сервер имеет 32 ГБ, а Xmx установлен на 20, а Xms равно 10. Я не вижу, что JVM заканчивается из оставшихся 12 ГБ (меньше суммы, предоставляемой нескольким другим процессам на машине). И мы застряли в режиме сервера из-за характера приложения и среды.
Когда я смотрю на использование памяти и процессора для приложения, я вижу постоянное использование памяти в течение всего дня, но затем внезапно перед тем, как он умрет, загрузка процессора достигает 100%, а использование памяти идет от X, до X + 2GB, до X + 4GB, до (иногда) X + 8GB, до смерти JVM. Похоже, что в JIT-компиляции происходит цикл повторного изменения размера массива.
Я теперь видел ошибку, связанную с вышеуказанным запросом 8 ГБ, а также запросами 16 ГБ. Все время метод, скомпилированный, когда это происходит, тот же. Это простой метод, который не имеет вложенных циклов, не рекурсии и не использует методы для объектов, которые возвращают статические поля-члены или поля экземпляра непосредственно с небольшим вычислением.
Так что у меня 2 вопроса:
- Кто-нибудь есть какие-либо предложения?
- Могу ли я проверить, есть ли проблема с компиляцией этого конкретного метода в тестовой среде, без запуска всего приложения, вызывающего JIT-компилятор напрямую? Или я должен запустить приложение и сказать ему, чтобы скомпилировать методы после гораздо меньшего количества вызовов (например, 2), чтобы заставить его скомпилировать метод почти мгновенно, а не в случайную точку дня?
@StephenC
Виртуальная машина Java является 1.6.0_20 (ранее 1.6.0_0), работающий на Solaris. Я знаю, что это компиляция, которая вызывает проблему по нескольким причинам.
ps
в секундах, ведущих к нему, показывает, что Java нить с ID, соответствующий компилятор нити (от jstack) принимает до 100% процессорного времениjstack
показывает, проблема заключается вJavaThread "CompilerThread1" daemon [_thread_in_native, id=34, ...]
Метод, упомянутый в jstack
, всегда один и тот, который мы написали. Если вы посмотрите на образец jstack
, вы поймете, что я имею в виду, но по очевидным причинам я не могу предоставить образцы кода или имена файлов. Я скажу, что это очень простой метод. Essentiall содержит несколько нулевых проверок, 2 для циклов, которые выполняют проверки равенства и, возможно, назначают значения, и некоторые простые вызовы методов после.Всего возможно 40 строк кода.
Эта проблема произошла 2 раза в 2 недели, хотя приложение запускается каждый день и перезапускается ежедневно. Кроме того, приложение не было под большой нагрузкой в любое время.
Было бы полезно, если бы вы сказали, какую версию JVM и уровень патча вы используете (и что это было до этого), и что ваша платформа для ОС/оборудования. Кроме того, почему вы пришли к выводу, что проблема возникает во время компиляции JIT, как вы выяснили метод, который компилируется ... и как выглядит код метода. –
Вы нашли удовлетворительное решение? –
Извините за * очень * поздний ответ - я уже отметил ответ – Phil