在try-catch中混淆无限递归的输出

Ruc*_*era 53 java stack-overflow

请考虑以下代码.

public class Action {
private static int i=1;
public static void main(String[] args) {
    try{
        System.out.println(i);
        i++;
        main(args);
    }catch (StackOverflowError e){
        System.out.println(i);
        i++;
        main(args);
    }
 }

}
Run Code Online (Sandbox Code Playgroud)

我得到了4338正确的价值.捕获StackOverflowError输出后如下连线.

4336
4337
4338 // up to this point out put can understand 
433943394339 // 4339 repeating thrice  
434043404340
4341
434243424342
434343434343
4344
4345
434643464346
434743474347
4348
434943494349
435043504350
Run Code Online (Sandbox Code Playgroud)

在这里考虑现场演示.它正常工作i=4330.其实这是怎么发生的?

供参考:

我做了以下代码来实现这里发生的事情.

public class Action {

    private static int i = 1;
    private static BufferedWriter bw;

    static {
        try {
            bw = new BufferedWriter(new FileWriter("D:\\sample.txt"));
        } catch (IOException e) {
           e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        bw.append(String.valueOf(i)+" ");
        try {
            i++;
            main(args);
        } catch (StackOverflowError e) {
            bw.append(String.valueOf(i)+" ");
            i++;
            main(args);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

现在上一期不存在.现在的价值i高达16824744改正,并进一步运行.我正在跳跃这可能会达到i=2,147,483,647(int的最大值)值而没有问题.

有一些问题println().下面也有类似的答案.但为什么?

实际原因是什么?

axt*_*avt 52

请注意,缺少换行符433943394339.它表明内部发生了错误System.out.println().

这里的关键点是System.out.println()需要一些堆栈空间才能工作,因此StackOverflowError抛出它System.out.println().

这是带有标记点的代码:

public static void main(String[] args) {
    try{
        System.out.println(i); // (1)
        i++;
        main(args); // (2)
    }catch (StackOverflowError e){
        System.out.println(i); // (3)
        i++;
        main(args); // (4)
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们假设当i =时,在递归的N级发生了什么4338:

  • 声明(1)在N级打印4338.产量4338\n
  • i 递增到 4339
  • 控制流程在(2)处进入N + 1级
  • N + 1级的语句(1)尝试打印4339,但在打印换行符之前System.out.println()抛出一个StackOverflowError.产量4339
  • StackOverflowError在N + 1级别被捕获,语句(3)尝试打印4339并再次以相同的原因失败.产量4339
  • 在N级捕获异常.此时有更多可用的堆栈空间,因此statement(3)尝试打印4339并成功(正确打印换行符).产量4339\n
  • i 增加并且控制流量在(4)处再次进入水平N + 1

在此之后情况重演4340.

我不确定为什么有些数字在没有换行符的序列之间打印相关,也许它与System.out.println()它使用的内部工作和缓冲区有关.

  • 用换行符打印的那些是这样做的,因为递归不会在剩余的1帧堆栈空间和剩余的0帧堆栈空间之间保持弹跳.该函数实际上是树递归的.每个函数调用最终都会返回,当你得到`n`帧返回而不是连续递归时,下一个`n`递归调用有足够的堆栈空间不会在`System.out.println`中溢出. (3认同)

Mar*_*aux 17

我怀疑发生的是这样的:

  1. 打印我
  2. 打印换行符
  3. 增加我
  4. 输入main
  5. 打印我
  6. 打印换行符
  7. 增加我
  8. 输入main
  9. 打印我
  10. StackOverflow被抛出(而不是打印换行)
  11. 回到主要,现在在捕获
  12. 打印我
  13. StackOverflow再次被抛出(而不是打印换行)
  14. 返回主要,在另一个捕获体.
  15. 打印我
  16. 打印换行符(现在不再失败,因为我们高出两级)
  17. 输入main,然后返回1.

  • 将"Catch"打印更改为"e"+ i`,您将获得半重复的"4370e4370e4370"组,这些组可以说每个数字的后两个打印位于"Catch"中 - http://ideone.com/BnHqjO (3认同)