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

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

原文:

  • 使用-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;
            }
        }
    }

结果:
2019120001714\_1.png

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

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

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » 关于第二版《深入理解java虚拟机》中“栈溢出”案例的不同看法

评论 1

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #1

    这一篇感觉也有问题,StackOverflowError不就是空间不足吗?创建很多本地变量导致内存不足可以理解。
    像最后的例子:并没有不断的创建本地变量鸭!

    大鸡腿3周前 (01-02)回复

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏