it-swarm.com.de

Was verursacht einen Java.lang.StackOverflowError?

Was kann ein Java.lang.StackOverflowError? Der Stapelausdruck, den ich erhalte, ist überhaupt nicht sehr tief (nur 5 Methoden).

83
Ivan

Überprüfen Sie, ob wiederkehrende Aufrufe für Methoden vorliegen. Es wird hauptsächlich verursacht, wenn eine Methode rekursiv aufgerufen wird. Ein einfaches Beispiel ist

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

    main.testMethod(1);
}

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

    System.out.println(i);
}

Hier das System.out.println (i); wird wiederholt zum Stapeln verschoben, wenn die testMethod aufgerufen wird.

58
Thota Srinath

Eines der (optionalen) Argumente für die JVM ist die Stapelgröße. Es ist -Xss. Ich weiß nicht, was der Standardwert ist, aber wenn die Gesamtmenge der Inhalte auf dem Stapel diesen Wert überschreitet, wird dieser Fehler angezeigt.

Im Allgemeinen ist eine unendliche Rekursion die Ursache dafür, aber wenn Sie das sehen würden, würde Ihr Stack-Trace mehr als 5 Frames haben.

Fügen Sie ein -Xss-Argument hinzu (oder erhöhen Sie den Wert von eins), um festzustellen, ob dies nicht mehr möglich ist.

21
nsayer

Was tatsächlich einen Java.lang.StackOverflowError verursacht, ist normalerweise eine unbeabsichtigte Rekursion. Bei mir ist es oft so, als wollte ich eine super Methode für die überlagerte Methode aufrufen. Wie in diesem Fall:

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); 
    }
}

Zunächst ist es hilfreich zu wissen, was hinter den Kulissen passiert, wenn wir eine Funktion aufrufen. Die Argumente und die Adresse, an der die Methode aufgerufen wurde, werden auf den Stack gepusht (siehe http://en.wikipedia.org/wiki/Stack_ (abstract_data_type) #Runtime_memory_management ), damit die aufgerufene Methode Greifen Sie auf die Argumente zu, damit die Ausführung nach Abschluss der aufgerufenen Methode nach dem Aufruf fortgesetzt werden kann. Aber da wir this.accelerate (accelerate, maxVelocity) rekursiv aufrufen (Rekursion ist lose, wenn eine Methode sich selbst aufruft. Weitere Informationen finden Sie unter http://en.wikipedia.org/wiki/Recursion_ (computer_science) =) Wir befinden uns in einer als unendliche Rekursion bekannten Situation und häufen die Argumente und die Rücksprungadresse weiterhin auf dem Aufrufstapel an. Da der Aufrufstapel eine begrenzte Größe hat, haben wir irgendwann keinen Platz mehr. Der fehlende Speicherplatz auf dem Aufrufstapel wird als Überlauf bezeichnet. Dies liegt daran, dass wir versuchen, mehr Stapelspeicher zu verwenden, als wir haben, und die Daten den Stapel buchstäblich überlaufen. In der Programmiersprache Java) führt dies zur Laufzeitausnahme Java.lang.StackOverflow und stoppt das Programm sofort.

Das obige Beispiel ist etwas vereinfacht (obwohl es mir mehr passiert, als ich zugeben möchte). Dasselbe kann auf eine rundere Art und Weise passieren, was es etwas schwieriger macht, es aufzuspüren. Im Allgemeinen ist der StackOverflow jedoch ziemlich einfach aufzulösen, sobald er auftritt.

Theoretisch kann es auch zu einem Stapelüberlauf ohne Rekursion kommen, in der Praxis scheint dies jedoch ein eher seltenes Ereignis zu sein.

10
ptoinson

Was ist Java.lang.StackOverflowError

Der Fehler Java.lang.StackOverflowError wird ausgegeben, um anzuzeigen, dass der Stapel der Anwendung aufgrund einer tiefen Rekursion erschöpft ist, d. H. Ihr Programm/Skript rekursiert zu tief.

Einzelheiten

Die Klasse StackOverflowError erweitert die Klasse VirtualMachineError, die angibt, dass die JVM ausgelaufen ist oder war von Ressourcen und kann nicht weiter arbeiten. Die VirtualMachineError, die die Error -Klasse erweitert, wird verwendet, um auf schwerwiegende Probleme hinzuweisen, die ein Anwendung sollte nicht fangen. Eine Methode darf solche Fehler nicht in ihrer throw -Klausel deklarieren, da es sich bei diesen Fehlern um abnormale Bedingungen handelt, mit deren Auftreten nie gerechnet wurde.

Ein Beispiel

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);
    }

}

Konsolenausgabe

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)

Erklärung

Wenn ein Funktionsaufruf von einer Java - Anwendung aufgerufen wird, wird ein Stapelrahmen auf dem Aufrufstapel zugewiesen. Das stack frame enthält die Parameter der aufgerufenen Methode, ihre lokalen Parameter und die Rücksprungadresse der Methode. Die Rücksprungadresse gibt den Ausführungspunkt an, von dem aus die Programmausführung fortgesetzt werden soll, nachdem die aufgerufene Methode zurückgekehrt ist. Wenn kein Platz für einen neuen Stack-Frame vorhanden ist, wird der StackOverflowError von der Java Virtual Machine (JVM) ausgelöst.

Der häufigste Fall, in dem der Stapel einer Java -Anwendung möglicherweise erschöpft sein kann, ist die Rekursion. In der Rekursion ruft sich eine Methode während ihrer Ausführung auf. Recursion Eine der leistungsstärksten allgemeinen Programmiertechniken, die jedoch mit Vorsicht angewendet werden muss, damit StackOverflowError vermieden werden.

Verweise

7
DebanjanB

Wenn ein Funktionsaufruf von einer Anwendung Java aufgerufen wird, wird ein Stapelrahmen auf dem Aufrufstapel zugewiesen. Der Stack-Frame enthält die Parameter der aufgerufenen Methode, ihre lokalen Parameter und die Rücksprungadresse der Methode.

Die Rücksprungadresse gibt den Ausführungspunkt an, von dem aus die Programmausführung fortgesetzt werden soll, nachdem die aufgerufene Methode zurückgekehrt ist. Wenn kein Platz für einen neuen Stack-Frame vorhanden ist, wird StackOverflowError von der Java Virtual Machine (JVM).

Der häufigste Fall, in dem der Stapel einer Java -Anwendung möglicherweise erschöpft sein kann, ist die Rekursion.

Bitte guck dir das an

So lösen Sie StackOverflowError

4
IntelliJ Amiya

Ich habe ein Programm mit Ruhezustand erstellt, in dem ich zwei POJO-Klassen mit jeweils einem Objekt als Datenelemente erstellt habe. Als ich in der Hauptmethode versuchte, sie in der Datenbank zu speichern, bekam ich auch diesen Fehler.

Dies liegt daran, dass beide Klassen sich gegenseitig referenzieren, wodurch eine Schleife erstellt wird, die diesen Fehler verursacht.

Überprüfen Sie daher, ob in Ihrem Programm solche Beziehungen vorhanden sind.

2
Singh

Stapelüberlauf-Ausnahmen können auftreten, wenn die Größe eines Thread-Stapels bis zum Erreichen des maximalen Grenzwerts weiter zunimmt.

Anpassen der Stapelgrößen (Xss und Xmso) -Optionen ...

Ich schlage vor, Sie sehen diesen Link: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Es gibt viele mögliche Ursachen für einen StackOverflowError, wie Sie in der sehen können Verknüpfung....

1

Lösung für Benutzer im Ruhezustand beim Parsen von Daten:

Ich hatte diesen Fehler, weil ich eine Liste von Objekten geparst habe, die auf beiden Seiten @OneToMany Und @ManyToOne Mit Jackson json zugeordnet wurden, was eine Endlosschleife verursachte.

Wenn Sie sich in der gleichen Situation befinden, können Sie dies mit den Annotationen @JsonManagedReference Und @JsonBackReference Lösen.

Definitionen von API:

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

    Anmerkung, die angibt, dass die mit Anmerkungen versehene Eigenschaft Teil einer wechselseitigen Verknüpfung zwischen Feldern ist. und dass seine Rolle "Eltern" (oder "Vorwärts") Link ist. Der Werttyp (Klasse) der Eigenschaft muss eine einzige kompatible Eigenschaft haben, die mit JsonBackReference kommentiert ist. Die Verknüpfung wird so behandelt, dass die mit dieser Anmerkung versehene Eigenschaft normal behandelt wird (normal serialisiert, keine spezielle Behandlung für die Deserialisierung). es ist die passende Rückreferenz, die eine besondere Behandlung erfordert

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

    Anmerkung, die angibt, dass die zugehörige Eigenschaft Teil einer bidirektionalen Verknüpfung zwischen Feldern ist. und dass seine Rolle "Kind" (oder "zurück") Link ist. Der Werttyp der Eigenschaft muss eine Bean sein: Es kann sich nicht um eine Auflistung, eine Zuordnung, ein Array oder eine Aufzählung handeln. Die Verknüpfung wird so behandelt, dass die mit dieser Anmerkung versehene Eigenschaft nicht serialisiert wird. und während der Deserialisierung wird sein Wert auf eine Instanz gesetzt, die über die "verwaltete" (Vorwärts-) Verbindung verfügt.

Beispiel:

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;

Eine andere Lösung ist die Verwendung von @JsonIgnore, Bei der das Feld auf null gesetzt wird.

0
Curse

In meinem Fall habe ich zwei Aktivitäten. In der zweiten Aktivität habe ich vergessen, die onCreate-Methode zu überarbeiten.

super.onCreate(savedInstanceState);
0
Julz Etnalob