Quelles sont les causes d'une erreur java.lang.StackOverflowError

Réponses:

60

Vérifiez tous les appels récusifs de méthodes. Cela est principalement dû à un appel récursif pour 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);
}

Ici, le System.out.println (i); sera poussé à plusieurs reprises dans la pile lorsque le testMethod est appelé.

Thota Srinath
la source
1
Je pense que tu as raison. Mais quelle en est la solution. Parce que nous élaborons une méthode de récusation, cela signifie que nous en avons besoin. Nous ne voulons pas changer de méthode. Alors, comment résoudre cette erreur?
Ajay Sharma
1
ou vous entrez dans une boucle infinie!
yalematta
@yalematta, toute méthode récursive doit avoir une condition pour quitter. Vérifiez donc si votre méthode récursive est correctement implémentée et se termine en fonction de certaines conditions.
Ayaz Alifov
@AjaySharma Nous devons concevoir notre système pour qu'il corresponde aux limites de mémoire disponible que nous avons assignées à JVM. Si le système se comporte mal avec l'erreur suivante, nous devons vérifier notre base de code.
Thota Srinath
23

L'un des arguments (facultatifs) de la JVM 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 de choses sur la pile dépasse cette valeur, vous obtiendrez cette erreur.

Généralement, la récursivité infinie en est la cause, 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) pour voir si cela disparaît.

nsayer
la source
10

Ce qui cause réellement une erreur java.lang.StackOverflowError est généralement une récursion involontaire. Pour moi, c'est souvent lorsque j'ai eu l'intention d'appeler une super méthode pour la méthode surchargé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); 
    }
}

Tout d'abord, 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 poussés sur la pile (voir http://en.wikipedia.org/wiki/Stack_(abstract_data_type)#Runtime_memory_management ) afin que la méthode appelée puisse accéder aux arguments et ainsi lorsque la méthode appelée est terminée, l'exécution peut se poursuivre après l'appel. Mais puisque nous appelons this.accelerate (accélération, maxVelocity) de manière récursive (la récursivité est vaguement quand 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écursivité infinie et nous continuons à empiler les arguments et l'adresse de retour sur la pile d'appels. Puisque la pile d'appels est de taille finie, nous finissons par manquer 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, cela entraîne l'exception d'exécution java.lang.StackOverflow et arrêtera 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 de manière plus circulaire, ce qui le rend un peu plus difficile à retrouver. Cependant, en général, le StackOverflow est généralement assez facile à résoudre, une fois qu'il se produit.

En théorie, il est également possible d'avoir un débordement de pile sans récursivité, mais en pratique, cela apparaîtrait comme un événement assez rare.

ptoinson
la source
8

Quel est java.lang.StackOverflowError

L'erreur java.lang.StackOverflowErrorest lancée pour indiquer que la pile de l'application a été épuisée, en raison d'une récursion profonde, c'est-à-dire que votre programme / script récursent trop profondément.

Détails

La classe StackOverflowErrorextend VirtualMachineErrorqui indique que la JVM a été ou a manqué de ressources et ne peut plus fonctionner. Le VirtualMachineErrorqui étend la Errorclasse est utilisé pour indiquer les problèmes graves qu'une application ne doit pas détecter. Une méthode peut ne pas déclarer de telles erreurs dans sa throwclause car ces erreurs sont des conditions anormales auxquelles on ne s'attendait jamais.

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 application Java, un cadre de pile est alloué sur la pile d'appels . Le stack framecontient 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 désigne le point d'exécution à partir duquel l'exécution du programme doit se poursuivre 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 StackOverflowErrorest alors lancé par la machine virtuelle Java (JVM).

Le cas le plus courant qui peut épuiser la pile d'une application Java est la récursivité. En récursivité, une méthode s'invoque lors de son exécution. Recursionl'une des techniques de programmation polyvalentes les plus puissantes, mais doit être utilisée avec prudence, afin d' StackOverflowErroréviter le.

Références

DebanjanB
la source
4

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 désigne le point d'exécution à partir duquel l'exécution du programme doit se poursuivre après le retour de la méthode invoquée. S'il n'y a pas d'espace pour un nouveau cadre de pile, l' erreur StackOverflowError est renvoyée par la machine virtuelle Java (JVM) .

Le cas le plus courant qui peut épuiser la pile d'une application Java est la récursivité.

Jetez un coup d'oeil s'il vous plait

Comment résoudre StackOverflowError

IntelliJ Amiya
la source
3

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

J'ai eu cette erreur parce que j'analysais une liste d'objets mappés des deux côtés @OneToManyet @ManyToOneà json en utilisant jackson, ce qui a provoqué une boucle infinie.

Si vous êtes dans la même situation, vous pouvez résoudre ce problème en utilisant @JsonManagedReferenceet des @JsonBackReferenceannotations.

Définitions de l'API:

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

    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 le lien «parent» (ou «avant»). 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 telle 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 arrière correspondante qui nécessite un traitement spécial

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

    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 le lien "enfant" (ou "retour"). Le type de valeur de la propriété doit être un bean: il ne peut pas s'agir d'une collection, d'une map, d'un tableau ou d'une énumération. La liaison est gérée de telle sorte que la propriété annotée avec cette annotation ne soit pas sérialisée; et pendant la désérialisation, sa valeur est définie sur l'instance qui a le lien «géré» (avant).

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 @JsonIgnorece qui mettra simplement null dans le champ.

Emerica
la source
2

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

Cela se produit parce que les deux classes se réfèrent l'une à l'autre, créant ainsi une boucle qui provoque cette erreur.

Alors, vérifiez si un tel type de relations existe dans votre programme.

Singh
la source
1

Des exceptions de dépassement de capacité de pile peuvent se produire lorsqu'une pile de threads continue de croître en taille jusqu'à atteindre la limite maximale.

Réglage des options des tailles 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 à une StackOverflowError, comme vous pouvez le voir dans le lien ....

Marzieh Ghadirinia
la source
Les réponses aux liens uniquement ne sont généralement pas acceptables; les liens se rompent, ce qui invaliderait totalement la réponse. Veuillez fournir un contexte, un code et une explication de la réponse au lieu d'un simple lien.
Jay le
0

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);
Julz Etnalob
la source
Même si c'est un moyen possible de soulever un StackOverflowError, je ne pense pas qu'il réponde à la question. Je pense qu'une bonne réponse devrait soit énumérer d'autres moyens d'obtenir cette exception que d'utiliser trop de récursivité, soit dire qu'il n'y a certainement pas d'autre moyen d'obtenir une telle exception que de la lancer manuellement.
JojOatXGME