JIT-компилятор Java вызывает OutOfMemoryError

Приложение, которое мы недавно начали время от времени сбой, с сообщением о "java.lang.OutOfMemoryError: запрошено 8589934608 байт для Chunk::new. Недостаточно места подкачки?".

Я посмотрел вокруг в сети, и везде предложения ограничены

  • вернуться к предыдущей версии Java
  • возиться с настройками памяти
  • использовать клиент вместо режима сервера

Возвращение к предыдущей версии означает, что в новой Java есть ошибка, но я не видел никаких признаков этого. Память не проблема вообще; на сервере доступно 32 ГБ, а для Xmx установлено значение 20, а для Xms - 10. Я не вижу, чтобы JVM исчерпала оставшиеся 12 ГБ (за вычетом суммы, выделенной нескольким другим процессам на машине). И мы застряли в режиме сервера из-за характера приложения и среды.

Когда я смотрю на использование памяти и ЦП для приложения, я вижу постоянное использование памяти в течение всего дня, но затем внезапно, перед тем как оно умирает, использование ЦП возрастает до 100%, а использование памяти изменяется от Х до Х + 2 ГБ, до X + 4 ГБ, (иногда) до X + 8 ГБ, до смерти JVM. Может показаться, что в JIT-компиляции происходит цикл повторного изменения размера массива.

Теперь я видел, что ошибка произошла с вышеупомянутым запросом 8GB, а также с запросами 16GB. Когда это происходит, метод компиляции всегда один и тот же. Это простой метод, который имеет не вложенные циклы, не имеет рекурсии и использует методы для объектов, которые возвращают статические поля-члены или поля-члены экземпляра напрямую без малейших вычислений.

Итак, у меня есть 2 вопроса:

  1. У кого-нибудь есть предложения?
  2. Могу ли я проверить, есть ли проблема при компиляции этого конкретного метода в тестовой среде, без запуска всего приложения и прямого вызова JIT-компилятора? Или я должен запустить приложение и сказать ему, чтобы он компилировал методы после гораздо меньшего количества вызовов (например, 2), чтобы заставить его компилировать метод почти мгновенно, а не в случайную точку дня?

@StephenC

JVM - это 1.6.0_20 (ранее 1.6.0_0), работающая на Solaris. Я знаю, что это компиляция, которая вызывает проблемы по нескольким причинам.

  1. ps в секундах, предшествующих этому, показывает, что поток Java с идентификатором, соответствующим потоку компилятора (из jstack), занимает 100% процессорного времени
  2. jstack показывает, что проблема в JavaThread "CompilerThread1" daemon [_thread_in_native, id=34, ...]

Метод, упомянутый в jstack всегда один и тот же, который мы написали. Если вы посмотрите на образец jstack В результате вы поймете, что я имею в виду, но по понятным причинам я не могу предоставить примеры кода или имена файлов. Я скажу, что это очень простой метод. Essentiall несколько пустых проверок, 2 для циклов, которые делают проверки на равенство и, возможно, присваивают значения, и некоторые простые вызовы методов после. Всего может быть 40 строк кода.

Эта проблема возникала 2 раза за 2 недели, хотя приложение запускается каждый день и перезапускается ежедневно. Кроме того, приложение не находилось под большой нагрузкой ни разу.

3 ответа

Вы можете исключить конкретный метод из JIT, создав файл с именем .hotspot_compiler и положить его в "рабочий каталог" ваших приложений. Просто добавьте запись в файл в следующем формате:

exclude com/amir/SomeClass someMethod

И вывод консоли от компилятора будет выглядеть так:

### Excluding compile:  com.amir.SomeClasst::someMethod

Для получения дополнительной информации прочитайте это. Если вы не уверены, что такое "рабочий каталог" ваших приложений, используйте

-XX:CompileCommandFile=/my/excludefile/location/.hotspot_compiler

в вашем скрипте запуска Java или командной строке.

В качестве альтернативы, если вы не уверены, что это ошибка компилятора JIT, и хотите посмотреть, сможете ли вы воспроизвести проблему без JIT, запустите ваш процесс Java с -Xint,

Хорошо, я сделал быстрый поиск и нашел ветку на форумах Sun Java, которая обсуждает это. Надеюсь, поможет.

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

Другие вопросы по тегам