我想检测一个OutOfMemoryError,进行堆转储,并自动退出Java程序.假设我的JVM有以下命令行参数:
-XX:OnOutOfMemoryError="kill -9 %p"
-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/tmp
Run Code Online (Sandbox Code Playgroud)
哪个先发生?进程是否会转储内存然后退出,反之亦然?
如果您使用的是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)
以防简短说明:
因此,如果您使用的是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随后
在Java版本8u92中,VM参数
-XX:+ExitOnOutOfMemoryError -XX:+CrashOnOutOfMemoryError 已添加,请参见发行说明。
ExitOnOutOfMemoryError
启用此选项时,JVM会在第一次出现内存不足错误时退出。如果您希望重新启动JVM实例而不是处理内存不足错误,则可以使用它。CrashOnOutOfMemoryError
如果启用此选项,则当发生内存不足错误时,JVM崩溃并产生文本和二进制崩溃文件。
改进请求:JDK-8138745(参数命名是错误的,虽然 JDK-8154713,ExitOnOutOfMemoryError代替ExitOnOutOfMemory)
你应该使用
ExitOnOutOfMemoryError 或 CrashOnOutOfMemoryError
和
堆转储内存不足错误
OpenJDK JVM(热点)首先进行堆转储,然后根据选择崩溃或退出。
为了更清楚地理解,您可以参考 JVM 源文件来处理这个特定的逻辑。
https://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/8641949eb21f/src/share/vm/utilities/debug.cpp
| 归档时间: |
|
| 查看次数: |
4452 次 |
| 最近记录: |