繁体   English   中英

递归调用期间的StackOverflowError

[英]StackOverflowError during recursive call

这个问题严格来说是理论上的,但我找不到答案。 考虑这个简短的程序:

public class SBtst {

    int i = 0;

    public static void main(String[] args) {
        new SBtst().rec();
    }

    public void rec() {
        System.out.println("rec is called "+i++);
        try {
            rec();
        } catch (StackOverflowError soe) {
            System.out.println("completed "+soe.getStackTrace().length);
        }
    }

}

执行后我输出类似于:

rec is called 10472
rec is called 10473
rec is called 10474Recursion completed 1024

问题是:

  1. 为什么println()没有完成新行,因为根据我的理解,当执行下一个rec()调用时它应该抛出一个错误并且它是在AFTER println()完成之后

  2. 为什么我在stackTrace数组中只获得1024个元素,但i等于10474? 这是否意味着不是每个调用都在堆栈跟踪中?

为什么这个例外显然是从println中抛出的?

为什么println()没有完成新行? 据我所知,执行下一个rec()调用时应抛出异常,但这将在println()完成后抛出。

你的理解不太正确。 在某些时候,堆栈看起来像:

…
rec()
  rec()
    rec()
      println()

Println也消耗资源(请参阅mattingly890的答案 ),并且没有理由在那时你无法达到极限。

为什么堆栈跟踪包含的帧数少于实际使用的帧数?

为什么我在堆栈跟踪中只获得1024个元素,即使至少使用了10474个? 这是否意味着不是每个调用都在堆栈跟踪中?

看看getStackTrace()的文档:

提供对printStackTrace()打印的堆栈跟踪信息的编程访问。 返回堆栈跟踪元素的数组,每个元素表示一个堆栈帧。 数组的第0个元素(假设数组的长度为非零)表示堆栈的顶部,这是序列中的最后一个方法调用。 通常,这是创建和抛出此throwable的点。 数组的最后一个元素(假设数组的长度为非零)表示堆栈的底部,这是序列中的第一个方法调用。

在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧。 在极端情况下,允许没有关于此throwable的堆栈跟踪信息的虚拟机从此方法返回零长度数组。 一般来说,此方法返回的数组将包含由printStackTrace打印的每个帧的一个元素。 写入返回的数组不会影响将来对此方法的调用。

在评论中, Peter Lawrey找到了文档 ,其中提到了堆栈大小的1024默认限制:

Java HotSpot VM选项

-XX:ThreadStackSize = 512

线程堆栈大小(以KB为单位)。 (0表示使用默认堆栈大小)[Sparc:512; Solaris x86:320(在5.0及更早版本中为256之前的版本); Sparc 64位:1024; Linux amd64:1024(5.0及更早版本中为0); 所有其他的0.]

不过,可能还有其他因素可以发挥作用。 例如,这些问题提到了另外两个选项:

第1部分:

OpenJDK实现中println()实现如下所示:

public void println(String x) {
    synchronized (this) {
        print(x);
        newLine();
    }
}

因此,对print(x)的调用可能会溢出堆栈,并且会在不newLine()方法的情况下引发StackOverflowError

第2部分:

Java API

在某些情况下,某些虚拟机可能会从堆栈跟踪中省略一个或多个堆栈帧...一般来说,此方法返回的数组将包含每个将由printStackTrace打印的帧的元素。

因此,JVM可以自由地对堆栈跟踪中存储的堆栈帧数施加限制,例如1024。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM