source

java.lang의 원인StackOverflowError(스택오버플로우오류)

lovecheck 2023. 1. 12. 22:08
반응형

java.lang의 원인StackOverflowError(스택오버플로우오류)

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가 호출되면 스택으로 반복적으로 푸시됩니다.

JVM에 대한 (임의) 인수 중 하나는 스택사이즈입니다-XSS입니다.기본값은 알 수 없지만 스택 상의 총 데이터 양이 이 값을 초과하면 오류가 발생합니다.

일반적으로 무한 재귀가 원인입니다만, 이 경우 스택트레이스에 5 프레임이 넘습니다

Xss 인수를 추가(또는 값을 증가)하여 이 값이 사라졌는지 확인합니다.

무엇이냐

이 오류는 깊은 재귀(프로그램/스크립트가 너무 깊게 재귀됨)로 인해 응용 프로그램의 스택이 모두 사용되었음을 나타냅니다.

상세

JVM의 리소스가 부족하거나 부족하여 더 이상 작동할 수 없음을 나타내는 확장 클래스입니다.클래스를 확장하는 는 응용 프로그램에서 검출해서는 안 되는 심각한 문제를 나타내기 위해 사용됩니다.메서드는 이러한 오류가 발생할 것으로 예상하지 못한 비정상적인 상태이기 때문에 해당 절에서 이러한 오류를 선언하지 않을 수 있습니다.

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 응용 프로그램에 의해 호출되면 스택프레임콜스택에 할당됩니다.에는 호출된 메서드의 파라미터, 로컬파라미터 및 메서드의 반환 주소가 포함되어 있습니다.반환 주소는 호출된 메서드가 반환된 후 프로그램 실행이 계속되어야 하는 실행 지점을 나타냅니다.새로운 스택 프레임을 위한 공간이 없는 경우 Java Virtual Machine(JVM; Java 가상 머신)에 의해 가 느려집니다.

Java 응용 프로그램의 스택을 소진할 수 있는 가장 일반적인 경우는 재귀입니다.재귀에서는 메서드가 실행 중에 호출됩니다.Recursion 가장 강력한 범용 프로그래밍 기법 중 하나이지만 이 방지되도록 주의하여 사용해야 합니다.

레퍼런스

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) 를 참조해 주세요).다만, 이것을 재귀적으로.accelerate(acceleration, maxVelocity)라고 부르고 있기 때문에(재귀는 메서드가 자신을 호출할 때 느슨하게 됩니다).상세한 것에 대하여는, http://en.wikipedia.org/wiki/Recursion_(computer_science)) 를 참조해 주세요.무한 재귀라고 불리는 상황이며, 콜 스택에 인수와 리턴 주소를 계속 축적하고 있습니다.콜 스택의 사이즈는 한정되어 있기 때문에 최종적으로 공간이 부족하게 됩니다.콜 스택의 공간 부족은 오버플로라고 불립니다.이는 우리가 가진 것보다 더 많은 스택스페이스를 사용하려고 하는데 데이터가 말 그대로 스택에 오버플로우하기 때문입니다.Java 프로그래밍 언어에서는 런타임 예외 java.lang이 발생합니다.StackOverflow를 지정하면 프로그램이 즉시 중지됩니다.

위의 예는 다소 간결합니다(제가 인정하고 싶은 것보다 더 많은 일이 발생하지만).같은 일이 더 많은 방법으로 일어날 수 있기 때문에 추적하기가 좀 더 어려워집니다.단, 일반적으로 StackOverflow는 일단 발생하면 해결하기가 매우 쉽습니다.

이론적으로는 재귀 없이 스택 오버플로를 발생시킬 수도 있지만 실제로는 매우 드문 현상입니다.

데이터 해석 시 휴지 상태 사용자를 위한 솔루션:

오브젝트 때문에 했습니다.@OneToMany ★★★★★★★★★★★★★★★★★」@ManyToOne무한 루프를 일으킨 잭슨을 이용해 json에게 전달했습니다.

, 이하려면 이 방법을 하면 됩니다.@JsonManagedReference ★★★★★★★★★★★★★★★★★」@JsonBackReference석입니니다다

API의 정의:

  • Json Managed Reference (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무효

함수 콜이 Java 응용 프로그램에 의해 호출되면 스택프레임이 콜스택에 할당됩니다.스택 프레임에는 호출된 메서드의 파라미터, 로컬파라미터 및 메서드의 반환 주소가 포함됩니다.

반환 주소는 호출된 메서드가 반환된 후 프로그램 실행이 계속되어야 하는 실행 지점을 나타냅니다.새로운 스택 프레임을 위한 공간이 없는 경우 Java Virtual Machine(JVM; Java 가상 머신)에 의해 StackOverflowError가 느려집니다.

Java 응용 프로그램의 스택을 소진할 수 있는 가장 일반적인 경우는 재귀입니다.

꼭 봐주세요

Stack Overflow Error 해결 방법

hibernate를 사용하여 프로그램을 만들었습니다.이 프로그램에서 두 개의 POJO 클래스를 만들었습니다.이 클래스는 서로의 오브젝트를 데이터 멤버로 하고 있습니다.메인 메서드에서 데이터베이스를 저장하려고 했을 때도 이 오류가 발생했습니다.

이는 두 클래스가 서로 참조하고 있기 때문에 루프가 생성되어 이 오류가 발생하기 때문입니다.

그러므로, 당신의 프로그램에 그런 종류의 관계가 있는지 확인해 보세요.

스택 오버플로 예외는 스레드스택의 크기가 최대 제한에 도달할 때까지 계속 증가할 때 발생할 수 있습니다.

스택 크기(XSS 및 Xmso) 옵션 조정 중...

다음 링크를 참조할 것을 권장합니다.http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Stack Overflow Error에는 링크에서 볼 수 있듯이 여러 가지 원인이 있을 수 있습니다.

저 같은 경우에는 두 가지 활동이 있습니다.두 번째 액티비티에서는 onCreate 메서드에 super를 붙이는 것을 잊었습니다.

super.onCreate(savedInstanceState);

나도 같은 문제를 겪고 있었어

Role.java

 @ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY,cascade = CascadeType.ALL)
 Set<BusinessUnitMaster> businessUnits =new HashSet<>();

Business Unit Master.java

@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinTable(
        name = "BusinessUnitRoles",
        joinColumns = {@JoinColumn(name = "unit_id", referencedColumnName = "record_id")},
        inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "record_id")}
)
private Set<Role> roles=new HashSet<>();

문제는 Business Unit Master와 Role을 생성할 때 Role Service를 위해 양쪽 개체를 저장해야 한다는 것입니다.자바

roleRepository.save(role);

BusinessUnitMasterService의 경우.자바

businessUnitMasterRepository.save(businessUnitMaster);

경우 toString은 엔티티 클래스의 예외를 발생시킵니다.시스템 로그를 체크하면 예외를 해결하는 데 도움이 됩니다.

내 경우 자식 클래스의 동등 및 해시 코드 클래스 메서드를 재정의해야 했습니다.

    @Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof MyClass)) return false;
    return id != null && id.equals(((MyClass) o).getId());
}

@Override
public int hashCode() {
    return getClass().hashCode();
}

여기 참조: vladmihalcea 기사

언급URL : https://stackoverflow.com/questions/3197708/what-causes-a-java-lang-stackoverflowerror

반응형