我正在运行一个我在Eclipse中用Java编写的程序。对于非常大的输入,该程序具有非常深的递归级别。对于较小的输入,程序运行正常,但是当给出大输入时,我得到以下错误:
Exception in thread "main" java.lang.StackOverflowError
这可以通过增加Java堆栈大小来解决吗?如果是这样,我该如何在Eclipse中执行此操作?
更新
@Jon Skeet
代码以递归方式遍历解析树以构建数据结构。因此,例如,代码将使用解析树中的节点执行一些工作,并在节点的两个子节点上调用自身,将它们的结果组合起来以给出树的整体结果。
递归的总深度取决于解析树的大小,但当递归调用的数量达到1000时,代码似乎失败(没有更大的堆栈)。
此外,我非常确定代码没有因为一个错误而失败,因为它适用于小输入。
答案 0 :(得分:76)
打开应用程序的运行配置(运行/运行配置...,然后在'Java应用程序'中查找应用程序条目)。
参数标签有一个文本框 Vm参数,输入-Xss1m
(或最大堆栈大小的更大参数)。默认值为512 kByte(SUN JDK 1.5 - 不知道供应商和版本之间是否有所不同)。
答案 1 :(得分:37)
可以通过增加堆栈大小来解决 - 但更好的解决方案将是如何避免递归这么多。递归解决方案总是可以转换为迭代解决方案 - 这将使您的代码更加干净地扩展到更大的输入。否则你真的会猜测要提供多少堆栈,这在输入中可能都不是很明显。
顺便说一句,你是否完全确定输入的大小而不是代码中的错误?这次递归有多深?
编辑:好的,看过更新后,我会亲自尝试重写它以避免使用递归。通常,Stack<T>
的“事情仍然可以做”是删除递归的一个很好的起点。
答案 2 :(得分:10)
在VM Arguments中添加标记-Xss1024k
。
您还可以使用mb
来增加-Xss1m
中的堆栈大小。
答案 3 :(得分:5)
在使用XSOM库
解析模式定义文件(XSD)时,我也遇到了同样的问题我能够将堆栈内存增加到208Mb,然后显示heap_out_of_memory_error
,我只能增加到320mb。
最终的配置是-Xmx320m -Xss208m
但是又一次运行了一段时间后失败了。
我的函数以递归方式打印模式定义的整个树,令人惊讶的是输出文件越过820Mb,定义文件为4 Mb(Aixm库),后者又使用50 Mb的模式定义库(ISO gml)。
我确信我必须避免递归,然后开始迭代和其他一些表示输出的方法,但是我很难将所有递归转换为迭代。
答案 4 :(得分:3)
您需要在Eclipse中具有启动配置才能调整JVM参数。
使用F11或Ctrl-F11运行程序后,在运行中打开启动配置 - &gt;运行配置...并在“Java应用程序”下打开您的程序。选择Arguments窗格,您将在其中找到“VM arguments”。
这是-Xss1024k
所在的地方。
如果您希望启动配置为工作区中的文件(以便您可以右键单击并运行它),请选择“公用”窗格,然后选中“另存为” - &gt;共享文件复选框并浏览到您想要启动文件的位置。我通常将它们放在一个单独的文件夹中,因为我们将它们检入CVS。
答案 5 :(得分:2)
如果参数-Xss
未执行此任务,请尝试从以下位置删除临时文件:
c:\Users\{user}\AppData\Local\Temp\.
这对我有用。
答案 6 :(得分:0)
查看Morris有序树遍历,它使用常量空间并在O(n)中运行(比正常的递归遍历长3倍 - 但是你在空间上节省了很多)。如果节点是可修改的,则可以在回溯到其根目录时(通过直接写入节点)保存子树的计算结果。
答案 7 :(得分:0)