我有一个软件,必须分析大文件。限制输入或提供无限内存不是一种选择,所以我必须忍受飞行的 OOME。因为 OOME 只杀死线程,所以我的软件在某种糟糕的状态下运行。
从外面看,一切看起来都很好,因为进程正在运行,但在内部它是脑死亡的。
我想拔掉插头。但是我该怎么做呢?
捕获 OOME 并不能保证下一行代码将被执行。例如 System.exit(9)。因此,JVM必须注意到OOM并自行设计。
他们的一些 vm 选项吗?
当您获得 OOME 时,您的内存可能非常低,并且日志记录并不总是有效。 解决此问题的一种方法是使用一种关闭方法,该方法保存一些内存,直到关闭才会释放。
例如
private static byte[] lastResort = new byte[256*1024];
public static void handleOOME(OutOfMemoryError oome) {
lastResort = null;
try {
LOG.fatal("Dying after ", oome);
} finally {
System.exit(-1);
}
}
Java 8 update 92 支持的 -XX:+ExitOnOutOfMemoryError
。
还可以使用 -XX:+CrashOnOutOfMemoryError
获取核心转储以供进一步调查。
还可以使用 -XX:+HeapDumpOnOutOfMemoryError
在 OOME 上生成堆转储,以便进一步调查。
来源:这个和这个。
因此,JVM必须注意到OOME并摧毁自己。 他们的一些 vm 选项吗?
不,没有。
但是,我不得不质疑您的假设,即您无法捕获OutOfMemoryError
并立即在异常处理程序中调用System.exit()
。
在实践中,它应该有效。 唯一的潜在问题是,如果您打电话给Runtime.setRunFinalizersOnExit(true)
...如果您以非零退出状态退出,即使这样也会被忽略。
(关于捕获 OOME 和其他随机Error
异常的警告是,JVM 可能不处于适合继续执行的状态。 但是打电话System.exit(nonzero)
不是那样做!