挑战接受 :)
StackOverflowError
不仅仅是通过递归发生的,还有其他方式 (挑战失败,请参见评论):
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();
}
}
};
}
functors[0].fun();
}
interface Functor
{
void fun();
}
}
使用标准的
javac Test.java
编译,然后使用
java -Xss104k Test 2> out
运行。之后,
more out
将会告诉你:
Exception in thread "main" java.lang.StackOverflowError
第二次尝试。
现在这个想法更加简单了。Java中的基本数据类型可以存储在栈上。因此,让我们声明很多double变量,比如double a1,a2,a3...
。这个脚本可以为我们编写、编译和运行代码:
#!/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
而且……我得到了一些意外的东西:
Aborted
这是与您的第二个问题相关的内容:它是100%重复的。
StackOverflowError发生在JVM实际溢出堆栈之前还是之后?
因此,在OpenJDK 20.0-b12的情况下,我们可以看到JVM首先爆炸了。但这似乎是一个错误,也许有人可以在评论中确认一下,因为我不确定。我应该报告这个问题吗?也许在某个更新的版本中已经修复了...根据JB Nizet在评论中提供的JVM specification link,JVM应该抛出StackOverflowError
而不是死机:
如果线程中的计算需要比允许的Java虚拟机堆栈更大,则Java虚拟机会抛出StackOverflowError。
第三次尝试。
public class Test {
Test test = new Test();
public static void main(String[] args) {
new Test();
}
}
我们希望创建一个新的Test对象。因此,它的(隐式)构造函数将被调用。但是,在此之前,Test的所有成员都会被初始化。因此,Test test = new Test()首先被执行...
我们希望创建一个新的Test对象...
更新:不幸的是,这是递归,我在
这里提出了相关问题。