如何在Java中捕获和恢复堆栈溢出?

9

我正在为一项任务编写分级程序,学生们在其中实现递归排序算法。这意味着可能会有几位学生提交导致堆栈溢出的破损代码。我希望能够捕获调用学生代码时发生的堆栈溢出,以便从他们的得分中扣除并继续进行其他测试。不幸的是,堆栈溢出似乎不像其他异常那样走标准路径-try/catch块似乎没有帮助。在堆栈溢出发生后,是否有一种方法可以将执行返回到我的代码中?我已经研究过使用线程来做到这一点,但似乎又回到无法使用try/catch的问题。

3个回答

14
当调用学生的方法时,您应该将调用嵌入到try-catch块中,并将Exception作为Throwables捕获。
请参阅以下代码: public class Test { /** * @param args */ public static void main(String[] args) { try { soe(); } catch (Throwable e) { System.out.println("Caught:" + e + ", everything went better than expected."); } } /** * Method producing StackOverflowError */ public static void soe() { soe(); } }
更多信息
当捕获Throwable时,您将捕获:
- 正常的Exception - 强制您使用try-catchthrows(例如IOException) - RuntimeException - 通过方法冒泡(例如NullPointerException) - Error - 例如StackOverflowError 请参阅官方Java文档中的Throwable对象。

1
这个。错误和异常都是Throwable的子类,这就是为什么错误会通过普通的异常捕获。它被设计成这样,以便Java中的关键故障(这就是错误)不会被程序员轻易地规避。 - Ibrahim Arief
1
@Matyas:但是在那个时候,程序能否继续执行呢?也就是说,堆栈会被重置还是进一步尝试做任何事情都会失败,因为没有可用的堆栈空间? - JRL
是的,它可以继续执行。当Throwable“冒泡”时,方法分配将从堆栈中移除。 一个简单的证明已经在上面的代码中了,当我们在catch块中调用一个新的方法(println)时,它会被分配到堆栈上。 - Matyas

2
您可以使用新的Process来启动他们的程序,然后重定向其错误流以检查堆栈溢出。

不需要这样做 - 请参考下面Matyas的答案。 - Paul Cager

1
你可以尝试在单独的JVM中运行每个程序。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接