원인은 무엇입니까 java.lang.StackOverflowError
? 내가 얻은 스택 인쇄물은 전혀 깊지 않습니다 (5 가지 방법 만).
답변:
메서드에 대한 반향적인 호출이 있는지 확인하십시오. 주로 메서드에 대한 재귀 호출이있을 때 발생합니다. 간단한 예는
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가 호출되면 스택에 반복적으로 푸시됩니다.
실제로 java.lang.StackOverflowError의 원인은 일반적으로 의도하지 않은 재귀입니다. 저에게는 종종 오버라이드 된 메서드에 대해 슈퍼 메서드를 호출하려고 할 때입니다. 이 경우와 같이 :
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 (acceleration, maxVelocity)를 재귀 적으로 호출하기 때문에 (재귀는 메서드가 스스로를 호출 할 때 느슨합니다. 자세한 내용은 http://en.wikipedia.org/wiki/Recursion_(computer_science)를 참조하십시오 .) 우리는 무한 재귀로 알려진 상황에 처해 있으며 인수를 계속 쌓고 호출 스택에 주소를 반환합니다. 호출 스택의 크기가 한정되어 있으므로 결국 공간이 부족합니다. 호출 스택의 공간 부족을 오버플로라고합니다. 이것은 우리가 가지고있는 것보다 더 많은 스택 공간을 사용하려고하고 데이터가 말 그대로 스택을 오버플로하기 때문입니다. Java 프로그래밍 언어에서 이로 인해 런타임 예외 java.lang.StackOverflow가 발생하고 프로그램이 즉시 중지됩니다.
위의 예는 다소 단순화되어 있습니다 (하지만 제가 인정하고 싶은 것보다 더 많이 발생합니다.) 동일한 일이 더 많은 방식으로 발생하여 추적하기가 조금 더 어려워 질 수 있습니다. 그러나 일반적으로 StackOverflow는 일반적으로 일단 발생하면 해결하기가 매우 쉽습니다.
이론적으로는 재귀없이 스택 오버플로가 발생할 수도 있지만 실제로는 매우 드문 이벤트 인 것처럼 보입니다.
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
호출 된 메소드, 로컬 매개 변수와 메소드의 반환 주소의 매개 변수가 포함되어 있습니다. 반환 주소는 호출 된 메서드가 반환 된 후 프로그램 실행이 계속되는 실행 지점을 나타냅니다. 새 스택 프레임을위한 공간이 없으면 StackOverflowError
JVM (Java Virtual Machine)에서을 처리합니다.
Java 애플리케이션의 스택을 소진시킬 수있는 가장 일반적인 경우는 재귀입니다. 재귀에서 메서드는 실행 중에 자신을 호출합니다. Recursion
가장 강력한 범용 프로그래밍 기술 중 하나이지만 StackOverflowError
이를 방지 하려면주의해서 사용해야합니다 .
Java 애플리케이션에서 함수 호출을 호출하면 스택 프레임이 호출 스택에 할당됩니다. 스택 프레임에는 호출 된 메서드의 매개 변수, 로컬 매개 변수 및 메서드의 반환 주소가 포함됩니다.
반환 주소는 호출 된 메서드가 반환 된 후 프로그램 실행이 계속되는 실행 지점을 나타냅니다. 새 스택 프레임을위한 공간이 없으면 JVM (Java Virtual Machine) 에서 StackOverflowError 가 발생합니다. .
Java 애플리케이션의 스택을 소진시킬 수있는 가장 일반적인 경우는 재귀입니다.
한번 봐주세요
데이터를 구문 분석 할 때 Hibernate 사용자를위한 솔루션 :
나는 양쪽에 매핑 된 개체의 목록을 구문 분석했기 때문에 나는이 오류를했다 @OneToMany
및@ManyToOne
무한 루프를 일으킨 jackson을 사용하여 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 ) :
연관된 속성이 필드 간의 양방향 연결의 일부임을 나타내는 데 사용되는 주석입니다. 그 역할은 "하위"(또는 "뒤로") 링크입니다. 속성의 값 유형은 빈이어야합니다. 컬렉션, 맵, 배열 또는 열거가 될 수 없습니다. 이 어노테이션으로 어노테이션이있는 특성이 직렬화되지 않도록 링크가 처리됩니다. deserialization 중에 해당 값은 "관리"(정방향) 링크가있는 인스턴스로 설정됩니다.
예:
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을 설정하는 것을 사용 하는 것입니다.
스택 오버플로 예외는 스레드 스택이 최대 제한에 도달 할 때까지 크기가 계속 증가 할 때 발생할 수 있습니다.
스택 크기 (Xss 및 Xmso) 옵션 조정 ...
: 나는 당신이이 링크를 참조 제안 http://www-01.ibm.com/support/docview.wss?uid=swg21162896을 ....하지 않고 StackOverflowError 많은 원인이 있습니다이 링크에서 볼 수 있듯이,
제 경우에는 두 가지 활동이 있습니다. 두 번째 활동에서 나는 onCreate 메소드에 super를 넣는 것을 잊었습니다.
super.onCreate(savedInstanceState);
StackOverflowError
이라고해도 질문에 답하고 있다고 생각하지 않습니다. 나는 적절한 대답이 너무 많은 재귀를 사용하는 것 보다이 예외를 얻는 다른 방법을 나열하거나 수동으로 던지는 것 외에는 그러한 예외를 얻는 다른 방법이 없다고 말해야한다고 생각합니다.