62

我正在运行一个我在 Eclipse 中用 Java 编写的程序。对于非常大的输入,该程序具有非常深的递归级别。对于较小的输入,程序运行良好,但是当输入较大时,我收到以下错误:

Exception in thread "main" java.lang.StackOverflowError

这可以通过增加 Java 堆栈大小来解决吗?如果可以,我该如何在 Eclipse 中做到这一点?

更新:

@乔恩斯基特

代码递归地遍历解析树以构建数据结构。因此,例如,代码将使用解析树中的一个节点做一些工作,并在该节点的两个子节点上调用自身,组合它们的结果以给出树的整体结果。

递归的总深度取决于解析树的大小,但是当递归调用的数量达到 1000 时,代码似乎会失败(没有更大的堆栈)。

此外,我很确定代码不会因为错误而失败,因为它适用于小输入。

4

8 回答 8

83

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

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

于 2010-01-24T13:52:20.570 回答
38

可以通过增加堆栈大小来解决——但更好的解决方案是找出如何避免如此多的递归。递归解决方案始终可以转换为迭代解决方案 - 这将使您的代码更干净地扩展到更大的输入。否则你真的会猜测要提供多少堆栈,这甚至可能从输入中看不出来。

顺便说一句,您绝对确定它失败是由于输入的大小而不是代码中的错误吗?这种递归到底有多深?

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

于 2010-01-24T13:40:02.507 回答
10

-Xss1024k在 VM 参数中添加标志。

您还可以mb使用-Xss1m例如增加堆栈大小。

于 2010-01-24T13:39:15.917 回答
5

我在使用 XSOM 库解析模式定义文件(XSD)时也遇到了同样的问题,

我能够将堆栈内存增加到 208MB,然后它显示heap_out_of_memory_error我只能增加到 320MB。

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

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

有了这一点,我确信我必须避免递归,然后开始迭代和其他一些表示输出的方式,但是我在将所有递归转换为迭代时遇到了一些麻烦。

于 2011-03-09T07:43:32.677 回答
3

您需要在 Eclipse 中进行启动配置才能调整 JVM 参数。

使用 F11 或 Ctrl-F11 运行程序后,在 Run -> Run Configurations... 中打开启动配置,然后在“Java Applications”下打开程序。选择“参数”窗格,您将在其中找到“VM 参数”。

这就是-Xss1024k去处。

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

于 2010-01-24T13:51:33.057 回答
2

当参数-Xss不起作用时,尝试从以下位置删除临时文件:

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

这对我有用。

于 2013-07-17T08:57:45.270 回答
0

看看 Morris 有序树遍历,它使用恒定空间并在 O(n) 中运行(比正常递归遍历长 3 倍 - 但您节省了大量空间)。如果节点是可修改的,那么您可以在回溯到其根时保存子树的计算结果(通过直接写入节点)。

于 2015-02-27T10:53:01.583 回答
0

使用JBOSS Server时,双击服务器:

在此处输入图像描述

转到“打开启动配置

在此处输入图像描述

然后更改最小最大内存大小(如 1G、1m):

在此处输入图像描述

于 2020-09-04T14:22:56.600 回答