Что может вызвать java.lang.StackOverflowError
? Распечатка стека, которую я получаю, не очень глубока (всего 5 методов).
Что вызывает java.lang.StackOverflowError
Ответ 1
Проверить любые призывы к использованию методов. В основном это вызвано, когда существует рекурсивный вызов метода. Простой пример:
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.
Ответ 2
Одним из (необязательных) аргументов JVM является размер стека. Это -Xss. Я не знаю, что такое значение по умолчанию, но если общее количество вещей в стеке превышает это значение, вы получите эту ошибку.
Как правило, причиной является бесконечная рекурсия, но если вы это видите, ваша трассировка стека будет иметь более 5 кадров.
Попробуйте добавить аргумент -Xss (или увеличить значение одного), чтобы увидеть, не исчезло ли это.
Ответ 3
Что на самом деле вызывает 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)), мы находимся в ситуация, известная как бесконечная рекурсия, и мы продолжаем складывать аргументы и возвращать адрес в стеке вызовов. Поскольку стек вызовов конечен по размеру, мы в конечном итоге заканчиваем пространство. Запуск пространства в стеке вызовов называется переполнением. Это связано с тем, что мы пытаемся использовать больше пространства стека, чем у нас, и данные буквально переполняют стек. На языке программирования Java это приводит к исключению среды выполнения java.lang.StackOverflow и немедленно остановит программу.
Приведенный выше пример несколько упрощен (хотя это случается со мной больше, чем я хотел бы признать). То же самое может произойти в более кругом пути, что затрудняет отслеживание. Однако, как правило, StackOverflow обычно легко разрешается, как только это происходит.
В теории также возможно переполнение стека без рекурсии, но на практике это будет довольно редкое событие.
Ответ 4
Что такое java.lang.StackOverflowError
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)
Explaination
Когда вызов функции вызывается приложением Java, в стеке вызовов выделяется кадр стека. stack frame
содержит параметры вызванного метода, его локальные параметры и адрес возврата метода. Адрес возврата обозначает точку выполнения, с которой выполнение программы должно продолжаться после возврата вызванного метода. Если для нового фрейма стека нет места, StackOverflowError
виртуальной машиной Java (JVM).
Наиболее распространенным случаем, который может исчерпать стек приложений Java, является рекурсия. В рекурсии метод вызывает себя во время выполнения. Recursion
один из самых мощных методов программирования общего назначения, но его следует использовать с осторожностью, чтобы избежать StackOverflowError
.
Рекомендации
Ответ 5
Когда вызов функции вызывается Java-приложением, стек стека выделяется в стеке вызовов. Фрейм стека содержит параметры вызываемого метода, его локальные параметры и обратный адрес метода.
Обратный адрес обозначает точку выполнения, из которой выполнение программы должно продолжаться после возврата вызванного метода. Если места для нового стека нет, то StackOverflowError вызывается виртуальной машиной Java (JVM).
Наиболее распространенным случаем, который может исчерпать стек приложений Java, является рекурсия.
Пожалуйста, посмотрите
Как решить StackOverflowError
Ответ 6
Я создал программу с hibernate, в которой я создал два класса POJO, как с объектом друг друга, так и с элементами данных. Когда в основном методе я попытался сохранить их в базе данных, я также получил эту ошибку.
Это происходит потому, что оба класса ссылаются друг на друга, поэтому создается цикл, который вызывает эту ошибку.
Итак, проверьте, существуют ли какие-либо подобные отношения в вашей программе.
Ответ 7
Исключения могут возникать, когда стек потоков продолжает расти в размере до достижения максимального предела.
Настройка параметров стека (Xss и Xmso)...
Предлагаю вам посмотреть эту ссылку: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Существует много возможных причин для StackOverflowError, как вы можете видеть в ссылке....
Ответ 8
Попробуйте очистить проект перед компиляцией
при компиляции и при внезапной сбое памяти это может вызвать эту ошибку...
Ответ 9
В моем случае у меня есть два вида деятельности. Во втором упражнении я забыл поставить super на метод onCreate.
super.onCreate(savedInstanceState);
Ответ 10
Решение для пользователей 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):
Аннотация, используемая для указания того, что связанное свойство является частью двусторонней связи между полями; и что его роль - "дочерняя" (или "обратная") ссылка. Тип значения свойства должен быть bean-компонентом: он не может быть коллекцией, картой, массивом или перечислением. Связывание обрабатывается так, что свойство, аннотированное этой аннотацией, не сериализуется; и во время десериализации его значение устанавливается равным экземпляру, который имеет "управляемую" (прямую) ссылку.
Пример:
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
который просто установит нулевое значение в поле.