为什么我在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方法之前打印了堆栈大小。
答案 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次)。
我不知道这是否有意义,但它确实很有趣。