web-dev-qa-db-fra.com

Quelles sont les causes d'une erreur Java.lang.StackOverflowError?

Qu'est-ce qui peut causer un Java.lang.StackOverflowError? L’impression de pile que j’obtiens n’est pas très profonde (seulement 5 méthodes).

83
Ivan

Vérifiez les appels récusatifs pour les méthodes. Cela est principalement dû à l’appel récursif d’une méthode. Un exemple simple est

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

    main.testMethod(1);
}

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

    System.out.println(i);
}

Voici le System.out.println (i); sera poussé à plusieurs reprises pour empiler lorsque le testMethod est appelé.

58
Thota Srinath

L'un des arguments (facultatif) de la machine virtuelle Java est la taille de la pile. C'est -Xss. Je ne sais pas quelle est la valeur par défaut, mais si la quantité totale d'éléments sur la pile dépasse cette valeur, vous obtiendrez cette erreur.

La cause est généralement la récursion infinie, mais si vous voyiez cela, votre trace de pile aurait plus de 5 images.

Essayez d’ajouter un argument -Xss (ou d’augmenter la valeur d’un argument) pour voir s’il disparaît.

21
nsayer

Ce qui provoque réellement une erreur Java.lang.StackOverflowError est généralement une récursion involontaire. Pour moi, c'est souvent quand j'ai eu l'intention d'appeler une super méthode pour la méthode masquée. Comme dans ce cas:

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

Premièrement, il est utile de savoir ce qui se passe dans les coulisses lorsque nous appelons une fonction. Les arguments et l'adresse de l'endroit où la méthode a été appelée sont placés sur la pile (voir http://en.wikipedia.org/wiki/Stack_ (type_abstrait_ abstraite) #Runtime_memory_management ) afin que la méthode appelée puisse accéder aux arguments et de sorte que l'exécution de la méthode appelée puisse se poursuivre après l'appel. Mais puisque nous appelons this.accelerate (accélération, maxVelocity) récursivement (la récursivité est approximative lorsqu'une méthode s'appelle elle-même. Pour plus d'informations, voir http://en.wikipedia.org/wiki/Recursion_ (computer_science) =) nous sommes dans une situation connue sous le nom de récursion infinie et nous continuons à empiler les arguments et l'adresse de retour sur la pile d'appels. Étant donné que la pile d'appels est de taille finie, nous manquons éventuellement d'espace. Le manque d'espace sur la pile d'appels est appelé débordement. En effet, nous essayons d'utiliser plus d'espace de pile que nous n'en avons et les données débordent littéralement de la pile. Dans le langage de programmation Java, il en résulte une exception d’exécution, Java.lang.StackOverflow, qui arrête immédiatement le programme.

L'exemple ci-dessus est quelque peu simplifié (bien que cela m'arrive plus que je ne voudrais l'admettre). La même chose peut se produire d'une manière plus complète, ce qui rend la tâche un peu plus difficile à retracer. Cependant, en général, StackOverflow est généralement assez facile à résoudre, une fois que cela se produit.

En théorie, il est également possible d'avoir un débordement de pile sans récursivité, mais dans la pratique, il semblerait que ce soit un événement assez rare.

10
ptoinson

Qu'est-ce que Java.lang.StackOverflowError

L'erreur Java.lang.StackOverflowError indique que la pile de l’application était épuisée en raison d’une récursion profonde, c’est-à-dire que votre programme/script est récursif trop profondément.

Détails

Le StackOverflowError s'étend VirtualMachineError classe qui indique que la machine virtuelle Java a été ou est à court de ressources et ne peut plus fonctionner. Le VirtualMachineError qui étend le Error est utilisé pour indiquer les problèmes graves qu’une application ne doit pas résoudre. Une méthode peut ne pas déclarer de telles erreurs dans sa clause throw car ces erreurs sont des conditions anormales inattendues.

Un exemple

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

}

Sortie de la console

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)

Explication

Lorsqu'un appel de fonction est appelé par une Java, un cadre de pile est alloué est alloué sur le pile d’appels . Le stack frame contient les paramètres de la méthode invoquée, ses paramètres locaux et l’adresse de retour de la méthode. L'adresse de retour indique le point d'exécution à partir duquel l'exécution du programme doit continuer après le retour de la méthode invoquée. S'il n'y a pas d'espace pour un nouveau cadre de pile, le StackOverflowError est lancé par le Java = Machine virtuelle (JVM).

Le cas le plus courant pouvant éventuellement épuiser une pile de l'application Java est la récursivité. Dans la récursivité, une méthode s'appelle elle-même lors de son exécution. Recursion est l’une des techniques de programmation polyvalente les plus puissantes, mais doit être utilisée avec prudence, afin de StackOverflowError à éviter.

Références

7
DebanjanB

Lorsqu'un appel de fonction est appelé par une application Java, un cadre de pile est alloué sur la pile d'appels. Le cadre de pile contient les paramètres de la méthode appelée, ses paramètres locaux et l'adresse de retour de la méthode.

L'adresse de retour indique le point d'exécution à partir duquel l'exécution du programme doit continuer après le retour de la méthode invoquée. S'il n'y a pas d'espace pour un nouveau cadre de pile, la StackOverflowError est renvoyée par le machine virtuelle Java (JVM).

Le cas le plus courant pouvant éventuellement épuiser une pile de Java) application est la récursivité.

Jetez un coup d'oeil s'il vous plait

Comment résoudre StackOverflowError

4
IntelliJ Amiya

J'ai créé un programme avec hibernate, dans lequel j'ai créé deux classes POJO, les deux avec un objet l'un à l'autre en tant que membres de données. Quand dans la méthode principale j'ai essayé de les enregistrer dans la base de données, j'ai aussi eu cette erreur.

Cela se produit parce que les deux classes se font référence, créant ainsi une boucle qui provoque cette erreur.

Alors, vérifiez si de telles relations existent dans votre programme.

2
Singh

Des exceptions de débordement de pile peuvent survenir lorsqu'une pile de threads continue de croître jusqu'à atteindre la limite maximale.

Réglage des options de taille de pile (Xss et Xmso) ...

Je vous suggère de voir ce lien: http://www-01.ibm.com/support/docview.wss?uid=swg21162896 Il existe de nombreuses causes possibles à StackOverflowError, comme vous pouvez le voir dans le lien....

1
Marzieh Ghadirinia

Solution pour les utilisateurs d'Hibernate lors de l'analyse des données:

J'ai eu cette erreur parce que j'étais en train d'analyser une liste d'objets mappés des deux côtés @OneToMany et @ManyToOne à json en utilisant jackson qui a provoqué une boucle infinie.

Si vous êtes dans la même situation, vous pouvez résoudre ce problème en utilisant @JsonManagedReference et @JsonBackReference annotations.

Définitions de l'API:

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

    L'annotation utilisée pour indiquer que la propriété annotée fait partie d'un lien bidirectionnel entre les champs; et que son rôle est "lien parent" (ou "forward"). Le type de valeur (classe) de la propriété doit avoir une seule propriété compatible annotée avec JsonBackReference. La liaison est gérée de sorte que la propriété annotée avec cette annotation soit gérée normalement (sérialisée normalement, pas de traitement spécial pour la désérialisation); c'est la référence correspondante qui nécessite une manipulation spéciale

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

    L'annotation utilisée pour indiquer que la propriété associée fait partie d'un lien bidirectionnel entre les champs; et que son rôle est "lien enfant" (ou "retour"). Le type de valeur de la propriété doit être un bean: il ne peut s'agir d'une collection, d'une map, d'un tableau ou d'une énumération. La liaison est gérée de sorte que la propriété annotée avec cette annotation ne soit pas sérialisée. et lors de la désérialisation, sa valeur est définie sur une instance possédant le lien "géré" (en aval).

Exemple:

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;

Une autre solution consiste à utiliser @JsonIgnore qui ne fera que mettre null au champ.

0
Curse

Dans mon cas, j'ai deux activités. Dans la deuxième activité, j'ai oublié de mettre super sur la méthode onCreate.

super.onCreate(savedInstanceState);
0
Julz Etnalob