gpt4 book ai didi

java - 捕获 java.lang.OutOfMemoryError?

转载 作者:IT老高 更新时间:2023-10-28 11:31:43 28 4
gpt4 key购买 nike

Documentation对于 java.lang.Error 说:

An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch

但是由于 java.lang.Errorjava.lang.Throwable 的子类,我可以捕捉到这种 Throwable。

我明白为什么捕获这种异常不是一个好主意。据我了解,如果我们决定捕获它,则捕获处理程序不应自行分配任何内存。否则会再次抛出OutOfMemoryError

所以,我的问题是:

  1. 捕获 java.lang.OutOfMemoryError 时是否有任何真实场景可能是个好主意?
  2. 如果我们决定捕获 java.lang.OutOfMemoryError,我们如何确保 catch 处理程序不会自行分配任何内存(任何工具或最佳实践)?

最佳答案

在许多情况下,您可能希望捕获 OutOfMemoryError,而根据我的经验(在 Windows 和 Solaris JVM 上),OutOfMemoryError 的死亡非常罕见-knell 到 JVM。

捕获 OutOfMemoryError 只有一个很好的理由,那就是优雅地关闭、干净地释放资源并尽可能记录失败的原因(如果仍然可以这样做的话)。

一般来说,OutOfMemoryError的发生是由于堆的剩余资源不能满足 block 内存分配。

Error 被抛出时,堆包含的已分配对象数量与分配不成功之前相同,现在是时候删除对运行时对象的引用以释放更多内存需要清理。在这些情况下,甚至可以继续,但这绝对是个坏主意,因为您永远无法 100% 确定 JVM 处于可修复状态。

证明OutOfMemoryError并不代表catch block 中JVM内存不足:

private static final int MEGABYTE = (1024*1024);
public static void runOutOfMemory() {
MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
for (int i=1; i <= 100; i++) {
try {
byte[] bytes = new byte[MEGABYTE*500];
} catch (Exception e) {
e.printStackTrace();
} catch (OutOfMemoryError e) {
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
long maxMemory = heapUsage.getMax() / MEGABYTE;
long usedMemory = heapUsage.getUsed() / MEGABYTE;
System.out.println(i+ " : Memory Use :" + usedMemory + "M/" +maxMemory+"M");
}
}
}

这段代码的输出:

1 : Memory Use :0M/247M
..
..
..
98 : Memory Use :0M/247M
99 : Memory Use :0M/247M
100 : Memory Use :0M/247M

如果运行一些关键的东西,我通常会捕获 Error,将其记录到 syserr,然后使用我选择的日志框架进行记录,然后继续释放资源并以干净的方式关闭。可能发生的最坏情况是什么? JVM 无论如何都快死了(或已经死了),并且通过捕获 Error 至少有清理的机会。

需要注意的是,您必须仅在可能进行清理的地方捕获这些类型的错误。不要到处乱扔catch(Throwable t) {} 或像那样胡说八道。

关于java - 捕获 java.lang.OutOfMemoryError?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2679330/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com