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.