StackOverflowError,在我的代码中找不到我调用的地方

时间:2011-07-27 16:06:48

标签: java exception stack-overflow

我在Java中有一个StackOverflowError并且它没有在我自己的代码中告诉我任何行,stacktrace的相关部分是:

java.lang.StringBuilder.append(StringBuilder.java:132)
java.util.AbstractMap.toString(AbstractMap.java:523)
java.lang.String.valueOf(String.java:2838)
java.lang.StringBuilder.append(StringBuilder.java:132)
java.util.AbstractCollection.toString(AbstractCollection.java:439)
java.lang.String.valueOf(String.java:2838)

我尝试从throwable获取堆栈跟踪,但由于某种原因它不包含相关节点,我试图在我的代码中找到一些关于错误位置的内容。此外,我已经尝试将堆栈大小减少到128k以更早地获得错误,但无济于事。

2 个答案:

答案 0 :(得分:6)

对于StackOverFlowError,堆栈跟踪经常被截断(因为它太长),这实际上无助于找到错误。

在您的情况下,假设您复制的部分是重复的部分,看起来您将地图添加到集合中,而集合又是原始地图的键或值,然后使用{其中一个对象的{1}}方法。

地图的toString()的默认实现(在AbstractMap中)然后使用其所有键和值调用toString(),这反过来将在这些上调用StringBuilder.append(...)。对于AbstractCollection,同样适用于集合的元素。

(Jon的回答中的例子与两个集合有关,而不是地图和集合。)

<强>解决方案:

  • 删除集合/地图中的周期。
  • 如果您的集合/地图图中需要循环:
    • 避免拨打toString(以及toString() / hashCode)或
    • 覆盖其中一个的equals方法以打破循环。

答案 1 :(得分:5)

这是一个会导致相同错误的示例,这可能有所帮助:

import java.util.*;

public class Test
{
    public static void main(String[] args)
    {
        List<Object> list1 = new ArrayList<Object>();
        List<Object> list2 = new ArrayList<Object>();
        list1.add(list2);
        list2.add(list1);
        String text = list1.toString();
        System.out.println(text);
    }
}

请注意,只需使用:

List<Object> list = new ArrayList<Object>();
list.add(list);
String text = list.toString();

... 产生错误。它足够聪明,可以注意到该集合是否立即本身 - 但不是嵌套本身。

当然,您可能没有使用相同的集合,因此可能会改变正在发生的事情 - 但希望这给您一个起点。