2010-01-24 96 views
55

我正在运行一个我在Eclipse中用Java编写的程序。该程序对于非常大的输入具有非常深的递归级别。对于较小的输入程序运行正常时,却给出了大投入,我得到以下错误:Java堆栈溢出错误 - 如何在Eclipse中增加堆栈大小?

Exception in thread "main" java.lang.StackOverflowError 

这个问题能得到解决,通过增加Java堆栈大小,如果是这样,我怎么做这在Eclipse?

更新:

@乔恩飞碟双向

的代码是为了建立一个数据结构递归遍历解析树。因此,例如,代码将使用分析树中的一个节点来做一些工作,并在节点的两个子节点上调用它自己,并将它们的结果组合起来以给出树的总体结果。

递归的总深度取决于解析树的大小,但代码似乎失败(没有更大的栈)时,递归调用的次数进入了1000。

而且我敢肯定,因为一个错误的代码不会失败,因为它适用于小的投入。

+7

这里有什么错... stackoverflow(.com)不是错误! :-) – 2010-01-24 14:37:31

回答

72

打开您的应用程序(运行/运行配置的运行配置 ...,然后在'Java应用程序'中查找应用程序条目)。

参数片具有一个文本框VM参数,输入-Xss1m(或最大堆栈大小更大的参数)。默认值是512 kByte(SUN JDK 1.5 - 不知道它是否因供应商和版本而异)。

+2

请注意以下问题:http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6316197 – 2010-01-24 15:02:40

10

在VM参数中添加标志-Xss1024k

您也可以通过使用-Xss1m例如增加堆栈大小mb

37

可以是通过增加堆栈大小固化 - 但更好的解决办法是制定出如何避免递归这么多。递归解决方案总是可以转换为迭代解决方案 - 这将使您的代码更加干净地扩展到更大的输入。否则,你真的会猜测提供了多少堆栈,这可能不是从输入中显而易见的。

你真的确认它的失败是由于输入,而不是在代码中的错误的大小,顺便说一下?这个递归有多深?

编辑:好的,在看到更新,我会亲自尝试重写它避免使用递归。通常有一个Stack<T>的“事情仍然存在”是删除递归的一个很好的起点。

+4

..或通过尾递归。 – BalusC 2010-01-24 13:46:43

+0

我不记得jvms上的尾递归状态。线索评论。 – 2010-01-24 14:08:34

+1

JVM尚未作为规则优化尾递归。我相信这是将JVM推广到非Java语言需要解决的问题之一。 – 2010-01-24 15:01:46

3

您需要在Eclipse内部具有启动配置才能调整JVM参数。

有两种F11或Ctrl-F11运行程序后,运行打开启动配置 - >运行配置...,然后在“Java应用程序”打开你的程序。选择Arguments窗格,您将在其中找到“VM参数”。

这是-Xss1024k去的地方。

如果您希望启动配置是工作区中的文件(因此您可以右键单击并运行它),请选择Common窗格,然后选中Save as - > Shared File复选框并浏览到您想要的位置启动文件。我通常有他们在一个单独的文件夹,因为我们检查他们到CVS。

5

我也有同样的问题,而使用XSOM库解析架构定义文件(XSD),

我能够增加堆栈内存高达208Mb则表明heap_out_of_memory_error为此我能只增加高达320MB。

最终配置为-Xmx320m -Xss208m,但后来又运行了一段时间并失败。

我的函数以递归方式打印模式定义的整个树,令人惊讶的是,输出文件跨越了820Mb,用于4 Mb(Aixm库)的定义文件,后者又使用了50 Mb的模式定义库(ISO gml)。

与此我相信我必须避免递归,然后开始迭代和其他方式来表示输出,但我没有什么麻烦将所有递归转换为迭代。

2

当参数-Xss没有做这项工作从尝试删除临时文件:

c:\Users\{user}\AppData\Local\Temp\. 

这奏效了我。

0

看Morris按顺序树遍历,它使用常量空间并运行在O(n)(最多比正常递归遍历长3倍 - 但在空间上节省很多)。如果节点是可修改的,则可以在回溯到其根目录时(通过直接写入节点)保存子树的计算结果。