• JVM异常之:栈溢出StackOverflowError


      在java虚拟机规范中,虚拟机栈和本地方法栈都会出现StackOverflowError和OutofMemoryError,程序计数器是java虚拟机中唯一一块不会产生error的内存区域。

    一、StackOverflowError(栈溢出)

    StackOverflowError代表的是,当栈深度超过虚拟机分配给线程的栈大小时就会出现此error。

    在eclipse中增加jvm参数见《eclipse调试时增加jvm参数

    示例1:

    package com.dxz.jvm;
    
    /**
     * @Described:栈层级不足
     * @VM args:-Xss128k
     */
    public class StackOverFlow {
        private int i;
    
        public void plus() {
            i++;
            plus();
        }
    
        public static void main(String[] args) {
            StackOverFlow stackOverFlow = new StackOverFlow();
            try {
                stackOverFlow.plus();
            } catch (Error e) {
                System.out.println("Error:stack length:" + stackOverFlow.i);
                e.printStackTrace();
            }
        }
    }

    -vm args-Xss128k  :说明后面是VM的参数,所以后面的其实都是JVM的参数了

    结果:

    Error:stack length:997
    java.lang.StackOverflowError
        at com.dxz.jvm.StackOverFlow.plus(StackOverFlow.java:11)

     示例2:

    package com.dxz.jvm;
    
    /**
     * @Described:递归Constructer
     * @VM args:-Xss128k
     */
    public class StackOverFlow2 {
    
        public class OneObject {
            OneObject oneObject = new OneObject();
        }
    
        public static void main(String[] args) {
            StackOverFlow2 stackOverFlow2 = new StackOverFlow2();
            try {
                OneObject oneObject = stackOverFlow2.new OneObject();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    结果:

    Exception in thread "main" java.lang.StackOverflowError
        at com.dxz.jvm.StackOverFlow2$OneObject.<init>(StackOverFlow2.java:10)

    反编译代码:

    package com.dxz.jvm;
    
    public class StackOverFlow2
    {
      public static void main(String[] args)
      {
        StackOverFlow2 stackOverFlow2 = new StackOverFlow2();
        try
        {
          StackOverFlow2 tmp13_12 = stackOverFlow2; tmp13_12.getClass(); OneObject localOneObject = new OneObject();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    
      public class OneObject
      {
        OneObject oneObject = new OneObject(StackOverFlow2.this);
    
        public OneObject()
        {
        }
      }
    }

     看下命令行:

    说明:在这里  constructer 中是调用 init , 而 static 是调用 cinit , 固我们如果将自己的对象放入到 static 中是不会造成递归的, 而如果将自己本身放到 constructer 中他就会不断的调用 init ,递归并不是马上返回,而是一层一层的保存在Stack里边,满足结束条件后才一层一层的返回。

    当Stack满了就抛出error了。 所以才发生了上面的java.lang.StackOverflowError 溢出错误。
    注意:是递归的错误,才出现Stack满的情况,而无限循环一般不会占用更多的内存或者具体的Stack,只是占cpu而已,所以不会抛此错误。
  • 相关阅读:
    join命令
    参与者模式
    字符串中的第一个唯一字符
    Git与SVN对比
    惰性模式
    .NET Conf 2020
    使用Github部署Azure应用服务
    Azure Terraform(一)入门简介
    打日志还能打出个线上Bug_ 太难了。。。
    让API并行调用变得如丝般顺滑的绝招
  • 原文地址:https://www.cnblogs.com/duanxz/p/8515821.html
Copyright © 2020-2023  润新知