Java-куча сбрасывает и закрывает - какой заказ?

Я хотел бы обнаружить OutOfMemoryError, взять кучу кучи и автоматически выйти из программы Java. Скажем, у меня есть следующие аргументы командной строки для моей JVM:

-XX:OnOutOfMemoryError="kill -9 %p"
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/tmp

Что происходит первым? Оказывает ли процесс память памяти, а затем выходит из нее или наоборот?

Ответ 1

Я предпочел бы полагаться на вызов script, который обрабатывает порядок более детерминистически, т.е.

-XX:OnOutOfMemoryError="/<SomeStandardLocation>/heapAndQuit.sh"

heapAndQuit.sh затем будет использовать метод для поиска pid текущего процесса. Один простой способ идентифицировать pid - использовать расположение файла журнала, которое ваш процесс пишет в

lsof | grep /var/tmp/<yourlogfileName> | cut -d " " -f1 | uniq

Затем я использую jmap для сброса и kill -9 впоследствии

Ответ 2

Если вы используете OpenJDK, вы можете быть уверены, что когда будете запускать команду, установленную параметром -XX: OnOutOfMemoryError.

Код, взятый из исходного кода OpenJDK. См.: debug.cpp

void report_java_out_of_memory(const char* message) {
  static jint out_of_memory_reported = 0;

  // A number of threads may attempt to report OutOfMemoryError at around the
  // same time. To avoid dumping the heap or executing the data collection
  // commands multiple times we just do it once when the first threads reports
  // the error.
  if (Atomic::cmpxchg(1, &out_of_memory_reported, 0) == 0) {
    // create heap dump before OnOutOfMemoryError commands are executed
    if (HeapDumpOnOutOfMemoryError) {    
      tty->print_cr("java.lang.OutOfMemoryError: %s", message);
      HeapDumper::dump_heap_from_oome();
    }

    if (OnOutOfMemoryError && OnOutOfMemoryError[0]) {
      VMError err(message);
      err.report_java_out_of_memory();
    }
  }
} 

На всякий случай короткое объяснение:

  • Прежде всего проверьте, была ли установлена ​​опция HeapDumpOnOutOfMemoryError. В этом случае запустите dump_heap_from_oome()
  • Sencondly, если была выбрана опция OnOutOfMemoryError, запустите report_java_out_of_memory()

Итак, если вы используете OpenJDK, ваш процесс будет выгружать память и затем выйти.

Ответ 3

В Java версии 8u92 аргументы VM

  • -XX:+ExitOnOutOfMemoryError
  • -XX:+CrashOnOutOfMemoryError

см. примечания к выпуску.

ExitOnOutOfMemoryError
Когда вы включаете эту опцию, JVM выходит на первое появление ошибки из памяти. Его можно использовать, если вы предпочитают перезапускать экземпляр JVM вместо обработки из ошибки памяти.

CrashOnOutOfMemoryError
Если этот параметр включен, ошибка при отсутствии памяти, JVM аварийно завершает работу и создает текст и двоичные файлы сбоя.

Запрос на улучшение: JDK-8138745 (неправильное имя параметра JDK-8154713, ExitOnOutOfMemoryError вместо ExitOnOutOfMemory)

Ответ 4

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