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(); } } }
以防简短说明:
- 首先检查是否设置了HeapDumpOnOutOfMemoryError选项。 在那种情况下运行dump_heap_from_oome()
- 如果设置了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采用了一些智能排序,首先执行堆转储而不是杀死机器。 但是,在我看来,你不应该依赖选项的顺序。