为什么没有捕获“java.lang.OutOfMemoryError:Java堆空间”?

我在Java Web应用程序中有一个线程导致java.lang.OutOfMemoryError:Java堆空间exception,但try / catch块没有捕获错误。

示例代码:

private void doSomeWork() { try { processData(); //Causes OutOfMemoryError System.out.println("This line does not execute"); } catch (Exception e) { System.out.println("Exception. This line does not execute."); //Log error } finally { System.out.println("finally. This line does execute"); System.out.println("Thread name: " + Thread.currentThread().getName()); } } 

输出:

最后。 这一行确实执行 
线程名称:_Worker-8
线程“_Worker-8”中的exceptionjava.lang.OutOfMemoryError:Java堆空间
 ... 

背景:

我最近接手了这个Java项目,我正在努力加快Java和这个项目的速度。 我是C#开发人员,所以我还不熟悉这个项目或Java。 我知道我可以使用-Xmx设置修复错误,但我有兴趣捕获此错误,以便我可以记录它。 错误未显示在任何日志文件中,并且输出在Eclipse中以调试模式显示在控制台中。

因为OutOfMemoryErrorError ,而不是Exception 。 由于OutOfMemoryError不是Exception的子类,因此catch (Exception e)不适用。

但是, OutOfMemoryError确实扩展了Throwable ,所以你应该能够捕获它。 这是关于何时(如果有的话)你应该捕获错误的SO讨论 。 通常,由于您无法对此做任何事情,因此建议不要在生产代码中捕获错误。 但是考虑到一个特殊情况,你试图调试正在发生的事情,它可能会有所帮助。

java.lang.OutOfMemoryError不扩展java.lang.Exception,因此它不是Exception。 OutOfMemoryError扩展了java.lang.Error。 如果你想捕捉错误试试这个:

 private void doSomeWork() { try { processData(); //Causes OutOfMemoryError System.out.println("This line does not execute"); } catch (Error e) { System.out.println("Exception. This line does not execute."); //Log error } finally { System.out.println("finally. This line does execute"); System.out.println("Thread name: " + Thread.currentThread().getName()); } } 

注意:Exception和Error扩展Throwable,因此您也可以使用Throwable来捕获它们。

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html

“〜错误”不是“〜例外”。

你必须抓住“错误”或“可扔”

OutOfMemoryError扩展了VirtualMachineError,而Exception直接扩展了Throwable。 所以它没有按照Java规范捕获。 如果您希望捕获所有exception,请将catch(Throwable e)添加到该子句中,您将拥有它。

我通常会做的是向线程添加一个’UncaughtExceptionHandler’,所以如果你有什么泄漏,至少有机会记录问题,也许做一些清理工作。