我同意并不同意这里的大多数回复。
有很多情况下,你可能希望赶上OutOfMemoryError
和我的经验(在Windows和Solaris JVM上),只有极少数情况下是对JVM的死亡跪拜。
抓住OutOfMemoryError
只有一个很好的理由,那就是优雅地关闭,干净地释放资源并尽可能记录失败原因(如果仍然可以的话)。
一般来说,OutOfMemoryError
是由于块存储器分配而导致的,这种分配不能满足堆的剩余资源。
当Error
被抛出堆载分配的对象是不成功的分配之前相同数量的,现在是放弃引用执行对象以释放可能需要进行清理,甚至更多的内存的时间。在这些情况下,甚至有可能继续,但这肯定是一个坏主意,因为你永远无法100%确定JVM处于可修复状态。
示范是OutOfMemoryError
并不意味着JVM内存不足的catch块:
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) {}
或者这样的废话。
类似的问题:http://stackoverflow.com/questions/1692230/is-it-possible-to-catch-out-of-memory-exception-in-java和http://stackoverflow.com/questions/ 352780/when-to-catch-java-lang-error – BalusC 2010-04-20 23:19:42
对于你的第一个问题,我会补充说我会捕获OutOfMemoryError以便(至少尝试)通知用户这个问题。以前,catch(Exception e)子句没有捕获到该错误,并且没有向用户显示任何反馈。 – 2013-10-25 10:14:27
有一些特定的情况,例如分配一个巨大的数组,在那里可以捕获围绕该操作的OOM错误并且恢复得相当好。但将try/catch放在一大块代码周围,试图恢复干净并继续运行可能不是一个好主意。 – 2014-07-18 11:55:55