StackOverflowError, не могу найти, где в моем коде я сделал вызов - PullRequest
2 голосов
/ 27 июля 2011

У меня есть StackOverflowError в Java, и он не сообщает мне ни одной строки в моем собственном коде, соответствующая часть трассировки стека:

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, но по какой-то причине он не содержит соответствующих узлов, я пытаюсь найти некоторую точку в моем коде относительно того, где находится ошибка. Также я попытался уменьшить размер стека до 128 КБ, чтобы получить ошибку раньше, но безрезультатно.

Ответы [ 2 ]

6 голосов
/ 27 июля 2011

Для StackOverFlowError трассировка стека часто усекается (так как она слишком длинная), что на самом деле не помогает найти ошибку.

В вашем случае, если вы скопировали ту часть, которая повторяется, похоже, что вы добавили карту в коллекцию, которая, в свою очередь, является ключом или значением исходной карты, а затем используете toString() метод на одном из этих объектов.

Реализация по умолчанию toString() для карты (в AbstractMap) затем вызывает StringBuilder.append(...) со всеми ее ключами и значениями, что в свою очередь вызовет toString для них. Для AbstractCollection то же самое справедливо для элементов коллекции.

(Пример в ответе Джона делает то же самое с двумя коллекциями вместо карты и коллекции.)

Решения:

  • Удалите циклы из вашей коллекции / графика карты.
  • Если вам нужны циклы в вашей коллекции / карте-графике:
    • избегайте звонков toString()hashCode / equals тоже) или
    • переопределить метод toString() одного из них, чтобы разорвать цикл.
5 голосов
/ 27 июля 2011

Вот пример, который вызовет ту же ошибку, которая может помочь:

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();

... не не выдало ошибку. Он достаточно умен, чтобы заметить, является ли коллекция немедленно внутри себя, но не вложенная внутри себя.

Конечно, вы не можете использовать одну и ту же коллекцию, так что это может изменить то, что происходит, но, надеюсь, это дало вам отправную точку.

...