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

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

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

哪个先发生? 进程是否会转储内存然后退出,反之亦然?

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

 -XX:OnOutOfMemoryError="//heapAndQuit.sh" 

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

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

然后我将使用jmap转储并jmap kill -9

如果您使用的是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(); } } } 

以防简短说明:

  1. 首先检查是否设置了HeapDumpOnOutOfMemoryError选项。 在那种情况下运行dump_heap_from_oome()
  2. 如果设置了OnOutOfMemoryError选项,则返回第二步,运行report_java_out_of_memory()

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

在Java版本8u92中的VM参数

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

添加了,请参阅发行说明 。

ExitOnOutOfMemoryError
启用此选项后,JVM会在第一次出现内存不足错误时退出。 如果您更喜欢重新启动JVM实例而不是处理内存不足错误,则可以使用它。

CrashOnOutOfMemoryError
如果启用此选项,则在发生内存不足错误时,JVM会崩溃并生成文本和二进制崩溃文件。

增强请求: JDK-8138745 (参数命名错误,但JDK-8154713 , ExitOnOutOfMemoryError而不是ExitOnOutOfMemory

我认为这在很大程度上取决于您使用的实际JVM实现。 我想相信使用的JVM采用了一些智能排序,首先执行堆转储而不是杀死机器。 但是,在我看来,你不应该依赖选项的顺序。