发生StackOverFlow错误时识别点

时间:2013-04-25 08:03:02

标签: java memory-leaks stack-overflow

我正在为学生编写一个教育计划,在那里他们可以看到不同算法在解决旅行商问题时的工作方式(时间消耗,状态的视觉表示等)。问题是,我不仅要展示好的算法,还要展示不好的算法。例如,我为TSP实施广度优先搜索算法(可怕的选择)。

程序本身是用Java编写的。我有一个单独的问题解决器算法线程,所有算法都实现了一个特定的接口,允许我在每次迭代后进行干预。

所有盲搜索算法都在N个节点(n =城市数)的树结构上运行,每个节点都是N个元素的数组,该实现在生成约50k个节点后产生StackOverFlow异常。我不想限制用户界面,以便可以使用有限的城市数量 - 模拟退火与数千个城市一起工作。

以下是问题: 是否有一些可靠的功能,我可以在一些指定的逻辑语句中使用,以便我可以确定系统即将崩溃的时刻? 东西是样式:if(System.memoryLeft()< = 100 / bytes /){//停止工作并采取行动

提前致谢。

3 个答案:

答案 0 :(得分:2)

检测它的最简单方法是抛出一个错误就是等到它抛出并出错并抓住它。

try {
   action();
} catch(StackOverflowError ste) {
   // you can't call anything here safely, but you can return or unwind the stack.
}

注意:最大堆栈大小因机器而异,并且基于命令行设置。它并非基于多个电话。

如果你真的关心这个问题,我建议更改代码不要使用递归,你完全避免这个问题。


问题是显示/记录的最大堆栈深度为1024.如果堆栈较长,则无法看到最初的堆栈深度。您可以做的是使用-Xss128k减少最大堆栈大小(如果您的JVM允许,则减少),这样您的堆栈跟踪将始终足够短以便捕获。

public static void main(String... ignored) {
    callMe(1);
}

private static void callMe(int i) {
    callMe(i);
}
使用较小的堆栈大小调用时

at Main.callMe(Main.java:42)
at Main.callMe(Main.java:42)
at Main.callMe(Main.java:42)

many deleted

at Main.callMe(Main.java:42)
at Main.callMe(Main.java:42)
at Main.callMe(Main.java:42)
at Main.main(Main.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

答案 1 :(得分:1)

链接到我的回答。 Simplest ways to cause stack overflow in C#, C++ and Java

此解释是针对Java,C,C ++语言的StackOverflowException背后的基本原因。

由于递归方法调用,Stackoverflow异常是由任何语言引起的。

假设您有一个调用自身的方法或无限递归循环的任何其他方法,那么它将导致Stacoverflowexception。这背后的原因是方法调用堆栈被提交并且它无法容纳ant其他方法调用。

方法调用堆栈看起来像这张图片。

enter image description here

解释 - 假设Main方法有五个语句,第三个方法调用methodA,然后main语句的执行在statement3处暂停,MethosA将被加载到调用堆栈中。然后方法A调用methodB。所以methodB也被加载到堆栈中。

因此,无限递归调用使调用堆栈得到填充。所以它不能再提供任何方法了。所以它抛出了StackOverflowException。

如何遇到它请参阅此链接

Computing method call stack size for checking StackOverflowException

我也在寻找这个查询的解决方案。

答案 2 :(得分:-1)

您可以使用public static int callbackCount跟踪堆栈中有多少方法调用。每次进入搜索功能时,请递增此计数器。每次你离开,减少它。这显然可以使用

完成
Thread.currentThread.getStackTrace().length;

我不太确定堆栈上允许多少次调用,但是如果你打印出这个值,那么找出它应该不会太难。

这样,您可以在遇到StackOverflowError之前检查可以进行的函数调用次数。