Java 堆转储和关闭 - 什么顺序?

2022-09-03 00:40:04

我想检测一个,采取堆转储,并自动退出Java程序。假设我的JVM有以下命令行参数:OutOfMemoryError

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

哪个先发生?进程是转储内存然后退出,还是相反?


答案 1

如果您使用的是OpenJDK,则可以确定何时要运行-XX:OnOutOfMemoryError选项设置的命令。

代码取自 OpenJDK 源代码。请参见:调试.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();
    }
  }
} 

以防万一简短的解释:

  1. 首先检查是否已设置堆转储OutOfMemoryError选项。在这种情况下,运行 dump_heap_from_oome()
  2. 如果设置了 OnOutOfMemoryError 选项,请运行 report_java_out_of_memory()

因此,可以肯定的是,如果您使用的是OpenJDK,您的进程将转储内存,然后退出。


答案 2

我宁愿依靠调用一个脚本来更确定地处理排序,即

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

然后,heapAndQuit.sh 将采用一种方法来查找当前进程。识别 pid 的一种简单方法是使用进程写入的日志文件位置pid

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

然后我将使用转储和随后jmapkill -9


推荐