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

the*_*n85 16 java jvm

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

-XX:OnOutOfMemoryError="kill -9 %p"
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/tmp
Run Code Online (Sandbox Code Playgroud)

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

Goo*_*man 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();
    }
  }
} 
Run Code Online (Sandbox Code Playgroud)

以防简短说明:

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

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


小智 7

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

-XX:OnOutOfMemoryError="/<SomeStandardLocation>/heapAndQuit.sh"
Run Code Online (Sandbox Code Playgroud)

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

lsof | grep /var/tmp/<yourlogfileName> | cut -d " " -f1 | uniq
Run Code Online (Sandbox Code Playgroud)

然后,我会用jmap抛售和kill -9随后


fla*_*nze 5

在Java版本8u92中,VM参数

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

已添加,请参见发行说明。

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

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

改进请求:JDK-8138745(参数命名是错误的,虽然 JDK-8154713,ExitOnOutOfMemoryError代替ExitOnOutOfMemory)


Sum*_*ava 5

你应该使用

ExitOnOutOfMemoryError 或 CrashOnOutOfMemoryError

和

堆转储内存不足错误

OpenJDK JVM(热点)首先进行堆转储,然后根据选择崩溃或退出。

为了更清楚地理解,您可以参考 JVM 源文件来处理这个特定的逻辑。

https://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/8641949eb21f/src/share/vm/utilities/debug.cpp