235 votes

Qu'est-ce qui cause une erreur de dépassement de pile?

Je l'ai cherché partout et impossible de trouver une réponse solide. Selon la documentation, Java jette un java.lang.StackOverflowError l'erreur dans les circonstances suivantes:

Levée lorsqu'un débordement de pile se produit parce qu'une application se répète trop profondément.

Mais cela soulève deux questions:

  • N'existe-il pas d'autres façons pour un débordement de la pile de se produire, non seulement par le biais de la récursivité?
  • Le StackOverflowError se produire avant que la JVM fait des débordements de la pile ou après?

Pour des précisions sur la deuxième question:

Lorsque Java jette le StackOverflowError, pouvez-vous supposer que la pile n'a pas l'écrire dans le tas? Si vous réduisez la taille de la pile ou le tas dans un try/catch sur une fonction qui déclenche un débordement de pile, pouvez-vous continuer à travailler? Est-ce documenté nulle part?

De réponses que je ne suis pas à la recherche:

  • Un StackOverflow se produit en raison de la mauvaise récursivité.
  • Un StackOverflow qui se passe quand le tas répond à la pile.

195voto

JB Nizet Points 250258

Il semble que vous êtes en train de penser qu'un stackoverflow erreur , c'est comme un débordement de la mémoire tampon d'exception dans les programmes destinés aux autochtones, lorsqu'il y a un risque d'écrire dans la mémoire, qui n'avait pas été alloué de la mémoire tampon, et donc de corrompre certains autres emplacements de la mémoire. Ce n'est pas du tout le cas.

JVM a une donnée de la mémoire allouée pour chaque pile de chaque sujet, et si une tentative d'appeler une méthode qui se passe pour remplir cette mémoire de la JVM renvoie une erreur. Tout comme il le ferait si vous étiez en train d'écrire à l'indice N d'un tableau de longueur N. Pas de corruption de la mémoire peut se produire. La pile ne peut pas écrire dans le tas.

Un StackOverflowError est à la pile ce qu'un OutOfMemoryError est au tas: il signale tout simplement que l'on n'a plus de mémoire disponible.

Description de la Machine Virtuelle Erreurs (§6.3)

StackOverflowError: La Machine Virtuelle Java de mise en œuvre de manquer d'espace de pile d'un thread, généralement parce que le fil est en train de faire un nombre illimité de récursive invocations comme un résultat d'une faute dans l'exécution du programme.

52voto

Ingo Points 21438

N'existe-il pas d'autres façons pour un débordement de la pile de se produire, non seulement par le biais de la récursivité?

Assurez-vous. Il suffit de garder appel de méthodes, sans jamais revenir. Vous aurez besoin d'un grand nombre de méthodes, sauf si vous permettre à la récursivité. En fait, il ne fait pas de différence: un stack frame est un cadre de pile, si elle est l'une des méthode récursive ou non, est la même.

La réponse à votre deuxième question est: Le stackoverflow est détectée lorsque la JVM tente d'allouer le cadre de pile pour le prochain appel et considère qu'il n'est pas possible. Donc, rien ne sera remplacé.

27voto

Adam Stelmaszczyk Points 7396

N'existe-il pas d'autres façons pour un débordement de la pile de se produire, non seulement grâce à la récursivité?

Défi accepté :) StackOverflowError sans récursivité (défi échoué, voir les commentaires):

public class Test
{
    final static int CALLS = 710;

    public static void main(String[] args)
    {
        final Functor[] functors = new Functor[CALLS];
        for (int i = 0; i < CALLS; i++)
        {
            final int finalInt = i;
            functors[i] = new Functor()
            {
                @Override
                public void fun()
                {
                    System.out.print(finalInt + " ");
                    if (finalInt != CALLS - 1)
                    {
                        functors[finalInt + 1].fun();
                    }
                }
            };
        }
        // Let's get ready to ruuuuuuumble!
        functors[0].fun(); // Sorry, couldn't resist to not comment in such moment. 
    }

    interface Functor
    {
        void fun();
    }
}

Compiler avec la norme javac Test.java et de courir avec java -Xss104k Test 2> out. Après, more out va vous dire:

Exception in thread "main" java.lang.StackOverflowError

Deuxième essai.

Maintenant, l'idée est encore plus simple. Primitifs en Java peuvent être stockées sur la pile. Donc, nous allons déclarer beaucoup de doubles, comme double a1,a2,a3.... Ce script peut écrire, compiler et exécuter le code pour nous:

#!/bin/sh

VARIABLES=4000
NAME=Test
FILE=$NAME.java
SOURCE="public class $NAME{public static void main(String[] args){double "
for i in $(seq 1 $VARIABLES);
do
    SOURCE=$SOURCE"a$i,"
done
SOURCE=$SOURCE"b=0;System.out.println(b);}}"
echo $SOURCE > $FILE
javac $FILE
java -Xss104k $NAME

Et... j'ai eu quelque chose d'inattendu:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f4822f9d501, pid=4988, tid=139947823249152
#
# JRE version: 6.0_27-b27
# Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea6 1.12.6
# Distribution: Ubuntu 10.04.1 LTS, package 6b27-1.12.6-1ubuntu0.10.04.2
# Problematic frame:
# V  [libjvm.so+0x4ce501]  JavaThread::last_frame()+0xa1
#
# An error report file with more information is saved as:
# /home/adam/Desktop/test/hs_err_pid4988.log
#
# If you would like to submit a bug report, please include
# instructions how to reproduce the bug and visit:
#   https://bugs.launchpad.net/ubuntu/+source/openjdk-6/
#
Aborted

Il est 100% répétitif. Est-ce lié à votre deuxième question:

Le StackOverflowError se produire avant que la JVM fait des débordements la pile ou après?

Ainsi, en cas de OpenJDK 20.0-b12, nous pouvons voir que la JVM d'abord explosé. Mais il semble comme un bug, peut-être quelqu'un peut confirmer que, dans les commentaires s'il vous plaît, parce que je ne suis pas sûr. Dois-je le signaler? C'est peut-être déjà résolu dans certaines version plus récente... Selon spécification de la JVM lien (donné par JB Nizet dans un commentaire) de la JVM doit lancer une StackOverflowError, de ne pas mourir:

Si le calcul d'un fil de discussion nécessite une plus grande Machine Virtuelle Java pile qu'il n'est autorisé, la Machine Virtuelle Java jette un StackOverflowError.

3voto

Lazy Coder Points 79

La cause la plus fréquente de StackOverFlowError est trop profonde ou d'une récursion infinie.

Par exemple:

public int yourMethod(){
       yourMethod();//infinite recursion
}

En Java:

Il y a two zones de mémoire de la tas et de la pile. L' stack memory est utilisé pour stocker les variables locales et la fonction d'appel, tout en heap memory est utilisé pour stocker les objets dans Java.

Si il n'y a pas de mémoire à gauche dans la pile pour stocker de l'appel d'une fonction ou d'une variable locale, JVM va jeter java.lang.StackOverFlowError

alors que si il n'y a plus d'espace de tas pour la création d'objet, de la JVM va jeter java.lang.OutOfMemoryError

3voto

GabrielBB Points 361

Il n'y a pas de "StackOverFlowException". Ce que tu veux dire est "StackOverFlowError".

Oui, vous pouvez continuer à travailler si vous l'attraper, car la pile est effacée lorsque vous faites cela, mais ce serait un mauvais et laid option.

Quand exactement l'erreur est levée ? Lorsque vous appelez une méthode et la JVM vérifie si il y a assez de mémoire pour le faire. Bien sûr, l'erreur est levée si il n'est pas possible.

  • Non, c'est la seule façon vous pouvez obtenir cette erreur: l'obtention de votre pile complète. Mais pas seulement grâce à la récursivité, également de l'appel de méthodes que l'infini appeler d'autres méthodes. C'est une très spécifiques d'erreur si aucun.
  • Il est jeté avant que la pile est pleine, exactement quand vous le vérifier. Où placeriez-vous les données si il n'y a pas d'espace disponible ? Primordial d'autres ? Faim.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X