Как обработать StackOverflowError в Java?

Версия Swift 4:

if var viewControllers = navigationController?.viewControllers {
    viewControllers[viewControllers.count - 1] = newViewController
    navigationController?.viewControllers = viewControllers
}
16
задан Michael Myers 4 June 2009 в 16:58
поделиться

8 ответов

Я не совсем понимаю, что вы имеете в виду под «дескриптором».

Вы определенно можете уловить эту ошибку:

public class Example {
    public static void endless() {
        endless();
    }

    public static void main(String args[]) {
        try {
            endless();
        } catch(StackOverflowError t) {
            // more general: catch(Error t)
            // anything: catch(Throwable t)
            System.out.println("Caught "+t);
            t.printStackTrace();
        }
        System.out.println("After the error...");
    }
}

, но это, скорее всего, плохая идея, если вы точно не знаете, что вы делаете.

16
ответ дан 30 November 2019 в 15:23
поделиться

Просто,

Посмотрите на трассировку стека, которую генерирует StackOverflowError, чтобы вы знали, где в вашем коде она встречается, и используйте ее, чтобы выяснить, как переписать код, чтобы он не вызывать сам себя рекурсивно (вероятная причина вашей ошибки), чтобы этого больше не произошло.

StackOverflowErrors - это не то, что нужно обрабатывать с помощью предложения try ... catch, но оно указывает на основной недостаток в логике ваш код, который вы должны исправить.

0
ответ дан 30 November 2019 в 15:23
поделиться

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

Если это не ошибка, вам нужно добавить счетчик или какой-либо другой механизм для остановки рекурсии до того, как рекурсия зайдет настолько глубоко, что вызовет переполнение стека.

Примером этого может быть ситуация, когда вы обрабатываете вложенный XML в модели DOM с рекурсивными вызовами, а XML вложен настолько глубоко, что вызывает переполнение стека вложенными вызовами (маловероятно, но возможно). Однако это должно быть довольно глубокое вложение, чтобы вызвать переполнение стека.

0
ответ дан 30 November 2019 в 15:23
поделиться

Я думаю, вы не можете - или, по крайней мере, это зависит от используемого jvm. Переполнение стека означает, что у вас нет места для хранения локальных переменных и возвращаемых адресов. Если ваш jvm выполняет некоторую форму компиляции, у вас также есть stackoverflow в jvm, а это означает, что вы не можете его обработать или поймать. Jvm должен быть завершен.

Может быть способ создать jvm, допускающий такое поведение, но это будет медленным.

Я не тестировал поведение с jvm, но в .net вы просто не можете справиться с stackoverflow. Даже попытка поймать не поможет. Поскольку java и .net полагаются на одну и ту же концепцию (виртуальные машины с jit), я подозреваю, что java будет вести себя одинаково. Присутствие исключения stackoverflow в .NET предполагает, что может быть какая-то виртуальная машина, которая позволяет программе отлавливать его, хотя обычно этого не происходит.

1
ответ дан 30 November 2019 в 15:23
поделиться

Как упоминалось многими в этом потоке, распространенной причиной этого является вызов рекурсивного метода, который не завершается. По возможности избегайте переполнения стека, и если вы это сделаете при тестировании, вы должны рассматривать это в большинстве случаев как серьезную ошибку. В некоторых случаях вы можете настроить размер стека потока в Java, чтобы он был больше для обработки некоторых обстоятельств (большие наборы данных, управляемые в локальном хранилище стека, длинные рекурсивные вызовы), но это увеличит общий объем памяти, что может привести к проблемам в количестве потоков, доступных в виртуальной машине. Обычно, если вы получаете это исключение, поток и любые локальные данные в этом потоке следует рассматривать как тост и не использовать (т. Е. Подозрительные и, возможно, поврежденные).

0
ответ дан 30 November 2019 в 15:23
поделиться

Возможно, вам захочется узнать, поддерживается ли ваш JVM параметр «-Xss» . Если это так, вы можете попробовать установить для него значение 512 КБ (по умолчанию 256 КБ в 32-разрядных Windows и Unix) и посмотреть, дает ли это что-нибудь (кроме как заставить вас сидеть дольше до вашего StackOverflowException). Обратите внимание, что это настройка для каждого потока, поэтому, если у вас много запущенных потоков, вы также можете увеличить настройки кучи.

7
ответ дан 30 November 2019 в 15:23
поделиться

Взгляните на сообщение Раймонда Чена При отладке переполнения стека вы хотите сосредоточиться на повторении рекурсивная часть . Отрывок:

Если вы исследуете свою базу данных отслеживания дефектов, пытаясь выяснить, известна ли эта проблема, поиск верхних функций в стеке вряд ли найдет что-нибудь интересное. Это потому, что переполнение стека обычно происходит в случайной точке рекурсии; каждое переполнение стека внешне отличается от любого другого, даже если это одно и то же переполнение стека.

Предположим, вы поете песню Frère Jacques , за исключением того, что вы поете каждый куплет на несколько тонов выше, чем предыдущий. В конце концов, вы достигнете вершины своего певческого диапазона, и где именно это происходит, зависит от того, где ваш вокальный лимит совпадает с мелодией. В мелодии каждая из первых трех нот представляет собой новый «рекордный максимум» (т. Е. Ноты выше, чем у любой другой спетой ноты), а новые рекордные ноты появляются в трех нотах третьего такта и последней записи. высокий во второй ноте пятого такта.

Если мелодия представляет использование стека программой, переполнение стека могло бы произойти в любом из этих пяти мест при выполнении программы. Другими словами, одна и та же скрытая рекурсия (музыкально представленная все более высоким исполнением мелодии) может проявляться пятью разными способами. «Рекурсия» в этой аналогии была довольно быстрой, всего за восемь тактов до повторения цикла. В реальной жизни цикл может быть довольно длинным, приводя к десяткам потенциальных точек, в которых может проявиться переполнение стека.

Если вы столкнулись с переполнением стека, то вы хотите игнорировать верхнюю часть стека, поскольку это просто фокусировка на конкретной ноте, которая выходит за пределы вашего вокального диапазона. Вы действительно хотите найти всю мелодию, поскольку это то, что является общим для всех переполнений стека с одной и той же основной причиной.

13
ответ дан 30 November 2019 в 15:23
поделиться

Вы, вероятно, имеете дело с бесконечной рекурсией.

То есть метод, который вызывает себя снова и снова

public void sillyMethod()
{
    sillyMethod();
}

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

17
ответ дан 30 November 2019 в 15:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: