是否可以在Java中捕获StackOverflowError?


27

我曾经以为不是,但是昨天我不得不这样做。这是一个使用Akka(JVM的参与者系统实现)来处理异步作业的应用程序。其中一位参与者执行了一些PDF操作,并且由于该库存在错误,因此有时会死于StackOverflowError

第二个方面是,如果捕获到任何JVM致命错误(例如,StackOverflowError),则将Akka配置为关闭其整个actor系统。

第三个方面是该参与者系统被嵌入到Web应用程序中(出于WTF-ish,传统,原因),因此当参与者系统关闭时,Web应用程序就不会被关闭。最终结果是,在StackOverflowError我们的工作处理应用程序上,该应用程序变成了一个空的Web应用程序。

作为快速解决方案,我不得不赶上了StackOverflowError被抛出的问题,以便不会破坏actor系统的线程池。这使我认为也许有时可以捕获此类错误,尤其是在这种情况下?当有一个线程池处理任意任务时?与A不同,OutOfMemoryError我无法想象A如何StackOverflowError使应用程序处于不一致状态。在发生此类错误后将清除堆栈,因此计算可以正常进行。但是也许我错过了一些重要的事情。

另外,请注意,我一开始就是要修复错误(事实上,几天前我已经在同一应用程序中修复了SOE),但是我真的不知道什么时候可能会出现这种情况。

为什么最好重新启动JVM进程而不是捕获StackOverflowError,将作业标记为失败,然后继续我的业务?

有什么令人信服的理由永远不赶上国有企业?除了“最佳实践”,这是一个模糊的术语,什么也没告诉我。


1
另一个选择是增加JVM上可用的堆栈空间
棘手怪胎

3
@ratchetfreak:StackOverflowExceptions通常是由于方法调用的不间断链-增加堆栈空间会增加新线程的内存成本,而没有任何好处。
13年

1
至少有一家国有企业是合法的,因为投入很大。不幸的是,用递归实现(Java的regex impl。)来处理它不是一个好主意。无论如何,即使保证可以终止计算,您也不知道新堆栈的大小是否足以用于其他计算。
Ionuț G. Stan 2013年

2
难道这不应该迁移到Sta ...哦,等等...没关系。 :-)
Blrfl 2013年

关于您的越野车库。您实际上应该将该pdf操作函数迁移到其自己的进程中,以便让OS杀死它。
Esben Skov Pedersen 2014年

Answers:


44

通常,如果做某事绝对是永远不会接受的,并且对此达成共识,那么语言实现者将不允许这样做。几乎没有如此一致的格言。(幸运的是,这就是让我们人类程序员从事工作的原因!)

看起来好像已经发现捕获此错误是最适合您的情况:它可以让您的应用程序正常工作,而所有其他替代方法则无法工作,这才是最终的结果。所有“最佳实践”都是对许多案例的长期经验的总结,通常可以用来代替对特定案例的详细分析以节省时间;在您的情况下,您已经完成了特定的分析并获得了不同的结果。恭喜,您有独立思考的能力!

(也就是说,肯定存在堆栈溢出的情况,可能导致应用程序不一致,就像内存耗尽一样。请想象一下,构造了某个对象,然后在嵌套内部方法调用的帮助下对其进行了初始化-如果其中一个抛出,则该对象可能很可能处于分配失败的状态,就像分配失败一样。但这并不意味着您的解决方案仍然不是最佳解决方案。)


3
谢谢。在我发现.NET发生StackOverflowException了不可捕获的异常之后,我的疑虑有所加强。我知道,这是一个不同的平台,但是我认为他们可能有原因。另外,关于对象初始化的观点很明确。这使我认为我应该在下面的一些抽象层中捕获该SOE,以免出现“错误”的SOE。
Ionuț G. Stan

14
+1:最佳做法应始终附有解释为什么 “最佳”以及在什么情况下它们是“最佳”的,以便您可以判断它们是否适用于您的特定情况。
Michael Borgwardt

situations here应该是situations where
2013年

2

我不知道这里是否有特定于JVM的风险,但总体而言似乎很明智。

例如,有些递归算法(如朴素的快速排序)log(n)在典型情况下具有堆栈深度,但在最坏的情况下,它们会降级到n可能炸毁堆栈的深度。

最坏的情况很少见,并且如果在部分排序的集合上重新开始排序,则不太可能再次发生,因此在发生堆栈溢出异常并重新开始工作而不是试图防止错误发生或终止时,很有意义。整个应用程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.