关于第二版《深入理解java虚拟机》中“栈溢出”案例的不同看法

13 篇文章 2 订阅
原文:
  • 使用-Xss参数减少栈内存容量。结果:抛出StackOverflowError异常,异常出现时输出的堆栈深度缩小。
  • 定义了大量的本地变量,增大此方法帧中本地变量表的长度。结果:抛出StackOverflowError,异常出现时输出的堆栈深度缩小。 书中代码如下:
public class JavaVMStackSOF {
    private int stackLength = 1;

    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static void main(String[] args) throws Throwable {

        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Exception e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    } 
  }

结果:

Exception in thread "main" java.lang.StackOverflowError
	at com.yanming.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
	at com.yanming.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
	at com.yanming.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)

解析:
  • 关于第一点没问题,使用-Xss参数减少栈的内存,确实会导致StackOverflowError。
  • 但是关于第二点,作者说是因为定义的大量的本地变量导致的StackOverflowError,个人却并不这么认为,虽然用递归无限使用stackLength++的操作,但是在stackLength++的同时,之前的stackLength值,由于已经没有地方引用了,会自动回收,所以并不是因为大量本地变量导致的。
  • 我们可以去掉原代码中的变量stackLength,再次输出结果看看:
public class JavaVMStackSOF {

    public void stackLeak() {
        stackLeak();
    }

    public static void main(String[] args) throws Throwable {

        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Exception e) {
            throw e;
        }
    }
}
  • 结果:
Exception in thread "main" java.lang.StackOverflowError
	at com.yanming.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
	at com.yanming.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)
	at com.yanming.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:14)

  • 可以看到,即使没有本地变量,很快就出现StackOverflowError的异常,这是因为代码中使用到了递归算法,stackLeak()方法无限的压入栈,由于栈的结构先进后出,先压入栈的方法无法释放,导致StackOverflowError。
  • 从另一个角度证明,并不是大量的本地变量导致的StackOverflowError。我们可以将原代码稍微改动下,stackLength++的操作,我们放入while循环中执行,看看有什么结果:
public class JavaVMStackSOF {
    private int stackLength = 1;

    public void stackLeak() {

        // 无限循环stackLength++;
        while (true) {
            stackLength++;
            System.out.println(stackLength);
        }
    }

    public static void main(String[] args) throws Throwable {

        JavaVMStackSOF oom = new JavaVMStackSOF();
        try {
            oom.stackLeak();
        } catch (Exception e) {
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

结果:
在这里插入图片描述

  • 我们可以看到程序会一直执行下去,并不会出现栈溢出错误。

所以,关于这一点个人认为书中的此案例出现栈溢出的原因是递归方法所知,并不是本地变量所致。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EmineWang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值