StackOverflow错误,java

时间:2018-05-23 20:03:19

标签: java stack-overflow

为什么我在StackOverflowError的情况下得到奇怪的输出?

public class Hello{  
    public static void main(String args[]){  
        System.out.println(new Exception().getStackTrace().length);  
        m1();  
    }  
    public static void m1(){  
        m2();  
    }  
    public static void m2(){  
        try{  
            m1();  
        }catch(StackOverflowError err){  
            System.out.println(err.getStackTrace().length);  
        }  
    }  
}  

Output (a)-
        1
        102410241024102410241024102410241024

Output (b) -
        1024

Output (c)-
        1
        1024   

当上面的代码执行时,我得到输出(a)。但是当我评论主要方法的第一行时,我得到输出(b)。

当我执行上面的代码时,我应该通过保持main方法中的第一行取消注释来获得输出(c)

为什么1024在输出(a)中打印了这么多次?

我试图通过提高StackOverflowError并故意捕获它来找出默认堆栈大小。我在从main方法调用m1方法之前打印了堆栈大小。

2 个答案:

答案 0 :(得分:1)

假设您已经在堆栈上

m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 

然后堆栈溢出,然后错误被这个堆栈捕获:

m1 - > m2 - > m1 - > m2 - > m1 - > m2 - > m1 - > m2

然后抛出另一个错误,因为你在catch子句中调用一个方法然后你抓住了这个堆栈:

m1 - > m2 - > m1 - > m2 - > m1 - > m2

然后抛出另一个错误,依此类推。这将继续,直到您的catch子句不再导致另一个错误。 另请注意,何时以及如何获得错误取决于JIT编译方法的时间和方式,这是不可预测的。

答案 1 :(得分:0)

首先,请注意,打印该行为并不重要,任何打印都足够了。

开头打印: 所以,通过一些调试,我注意到在方法PrintStream.write(String s)中有一行textOut.flushBuffer()意外失败。其结果基本上是,请求的String被添加到缓冲区,但缓冲区没有被刷新,并且新行没有被添加到缓冲区,因为它是一个单独的步骤,并且在调用点之后很久失败了。然后在最后,在最后一次打印时,此方法成功完成,因此您的String将与之前的所有字符串一起打印到控制台,因为它们在缓冲区中等待(1024次多次)。

一开始没有打印:程序在所有打印尝试中都没有达到textOut.flushBuffer(),它甚至没有达到println方法本身。它可能是因为它必须在整个过程中初始化一些类,因为它之前没有完成(比如开头的打印)并且它不能,因为堆栈溢出。因此,与之前在开头打印的情况不同,缓冲区中没有添加任何内容,因此最后我们只打印了一个字符串(1024次,1次)。

我不知道这是否有意义,但它确实很有趣。