Что вызывает java.lang.StackOverflowError - PullRequest
83 голосов
/ 07 июля 2010

Что может вызвать java.lang.StackOverflowError?Полученная мной распечатка стека совсем не глубокая (всего 5 методов).

Ответы [ 9 ]

58 голосов
/ 08 июля 2013

Проверка любых рекурсивных вызовов методов.В основном это вызвано, когда есть рекурсивный вызов метода.Простой пример:

public static void main(String... args) {
    Main main = new Main();

    main.testMethod(1);
}

public void testMethod(int i) {
    testMethod(i);

    System.out.println(i);
}

Здесь System.out.println (i);будет повторно помещаться в стек при вызове метода testMethod.

21 голосов
/ 07 июля 2010

Одним из (необязательных) аргументов JVM является размер стека.Это -Xss.Я не знаю, каково значение по умолчанию, но если общее количество материала в стеке превышает это значение, вы получите эту ошибку.вы видели, что ваша трассировка стека будет иметь более 5 кадров.

Попробуйте добавить аргумент -Xss (или увеличить значение единицы), чтобы проверить, исчезнет ли это.

10 голосов
/ 20 июня 2013

То, что фактически вызывает ошибку java.lang.StackOverflowError, обычно является непреднамеренной рекурсией.Для меня это часто, когда я намеревался вызвать супер метод для метода overidden.Например, в этом случае:

public class Vehicle {
    public void accelerate(float acceleration, float maxVelocity) {
        // set the acceleration
    }
}

public class SpaceShip extends Vehicle {
    @Override
    public void accelerate(float acceleration, float maxVelocity) {
        // update the flux capacitor and call super.accelerate
        // oops meant to call super.accelerate(acceleration, maxVelocity);
        // but accidentally wrote this instead. A StackOverflow is in our future.
        this.accelerate(acceleration, maxVelocity); 
    }
}

Во-первых, полезно знать, что происходит за кулисами, когда мы вызываем функцию.Аргументы и адрес, где был вызван метод, помещаются в стек (см. http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management), чтобы вызываемый метод мог получить доступ к аргументам и чтобы после завершения вызванного метода выполнение могло продолжаться после вызова.Но так как мы вызываем this.accelerate (ускорение, maxVelocity) рекурсивно (рекурсия происходит свободно, когда метод вызывает сам себя. Для получения дополнительной информации см. http://en.wikipedia.org/wiki/Recursion_(computer_science)), мы находимся в ситуации, известной как бесконечная рекурсия, и мы продолжаем накапливать аргументы иадрес возврата в стеке вызовов. Поскольку стек вызовов имеет конечный размер, в конечном итоге у нас заканчивается пространство. Недостаточно места в стеке вызовов называется переполнением. Это происходит потому, что мы пытаемся использовать больше места в стеке, чем мыhave и данные буквально переполняют стек. В языке программирования Java это приводит к исключению времени выполнения java.lang.StackOverflow и немедленно останавливает программу.

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

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

5 голосов
/ 15 декабря 2017

Что такое java.lang.StackOverflowError

Выдается ошибка java.lang.StackOverflowError, указывающая, что стек приложения исчерпан из-за глубокой рекурсии, т.е. ваша программа /сценарий слишком глубоко повторяется.

Подробности

StackOverflowError расширяет VirtualMachineError класс, который указывает, что JVM была или закончиласьресурсов и не может работать дальше.VirtualMachineError, расширяющий класс Error, используется для указания тех серьезных проблем, которые приложение не должно улавливать.Метод может не объявлять такие ошибки в своем предложении throw, поскольку эти ошибки являются ненормальными условиями, которые никогда не ожидались.

Пример

Minimal, Complete, and Verifiable Example:

package demo;

public class StackOverflowErrorExample {

    public static void main(String[] args) 
    {
        StackOverflowErrorExample.recursivePrint(1);
    }

    public static void recursivePrint(int num) {
        System.out.println("Number: " + num);

        if(num == 0)
            return;
        else
            recursivePrint(++num);
    }

}

Консольный вывод

Number: 1
Number: 2
.
.
.
Number: 8645
Number: 8646
Number: 8647Exception in thread "main" java.lang.StackOverflowError
    at java.io.FileOutputStream.write(Unknown Source)
    at java.io.BufferedOutputStream.flushBuffer(Unknown Source)
    at java.io.BufferedOutputStream.flush(Unknown Source)
    at java.io.PrintStream.write(Unknown Source)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
    at java.io.OutputStreamWriter.flushBuffer(Unknown Source)
    at java.io.PrintStream.newLine(Unknown Source)
    at java.io.PrintStream.println(Unknown Source)
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:11)
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)
    .
    .
    .
    at demo.StackOverflowErrorExample.recursivePrint(StackOverflowErrorExample.java:16)

Объяснение

Когда вызов функции вызывается приложением Java, кадр стека выделяется в стеке вызовов .stack frame содержит параметры вызванного метода, его локальные параметры и адрес возврата метода.Адрес возврата обозначает точку выполнения, с которой выполнение программы должно продолжаться после возврата вызванного метода.Если для нового кадра стека нет места, виртуальная машина Java (JVM) выбрасывает StackOverflowError.

Наиболее распространенный случай, который может исчерпать приложение Java.стек рекурсия.В рекурсии метод вызывает себя во время выполнения.Recursion один из самых мощных методов программирования общего назначения, но его следует использовать с осторожностью, чтобы избежать StackOverflowError.

Ссылки

4 голосов
/ 28 сентября 2015

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

Адрес возврата обозначает точку выполнения, с которой выполнение программы должно продолжаться после возврата вызванного метода.Если для нового кадра стека нет места, 1006 * Виртуальная машина Java (JVM) *1003* 1008 *.

* 1010 генерирует *1003* StackOverflowError .Наиболее распространенным случаем, который может исчерпать стек Java-приложения, является рекурсия.

Пожалуйста, посмотрите

Как решить StackOverflowError

2 голосов
/ 03 апреля 2014

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

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

Итак, проверьте, существуют ли такие отношения в вашей программе.

1 голос
/ 02 сентября 2017

Исключения переполнения стека могут возникать, когда размер стека потока продолжает увеличиваться до достижения максимального предела.

Настройка параметров размера стека (Xss и Xmso) ...

Предлагаю вам посмотреть эту ссылку: http://www -01.ibm.com / поддержка / docview.wss? UID = swg21162896 Существует множество возможных причин StackOverflowError, как вы можете видеть по ссылке ....

0 голосов
/ 06 июня 2019

Решение для пользователей Hibernate при разборе данных:

У меня была эта ошибка, потому что я анализировал список объектов, отображенных с обеих сторон @OneToMany и @ManyToOne в json, используя Джексона, что вызвало бесконечный цикл.

Если вы находитесь в такой же ситуации, вы можете решить эту проблему с помощью аннотаций @JsonManagedReference и @JsonBackReference.

Определения из API:

  • JsonManagedReference (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonManagedReference.html):

    Аннотация, используемая для указания того, что аннотированное свойство является частью двусторонней связь между полями; и что его роль "родитель" (или "вперед") ссылка на сайт. Тип значения (класс) свойства должен иметь один совместимый свойство аннотировано с помощью JsonBackReference. Связи обрабатываются такими что свойство, аннотированное этой аннотацией, обрабатывается нормально (сериализуется нормально, без специальной обработки для десериализации); это соответствующая обратная ссылка, требующая специальной обработки

  • JsonBackReference: (https://fasterxml.github.io/jackson-annotations/javadoc/2.5/com/fasterxml/jackson/annotation/JsonBackReference.html):

    Аннотация, используемая для указания того, что связанное свойство является частью двусторонняя связь между полями; и что его роль "ребенок" (или "назад") ссылка. Тип значения свойства должен быть бином: не может быть Коллекция, Карта, Массив или Перечень. Связывание обрабатывается так, что свойство, помеченное этой аннотацией, не сериализуется; а также во время десериализации его значение устанавливается равным экземпляру, который имеет «управляемая» (прямая) ссылка.

Пример:

Owner.java:

@JsonManagedReference
@OneToMany(mappedBy = "owner", fetch = FetchType.EAGER)
Set<Car> cars;

Car.java:

@JsonBackReference
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "owner_id")
private Owner owner;

Другим решением является использование @JsonIgnore, которое будет просто устанавливать в поле значение null.

0 голосов
/ 19 февраля 2017

В моем случае у меня есть два вида деятельности.Во втором упражнении я забыл поставить super на метод onCreate.

super.onCreate(savedInstanceState);
...