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而已,所以不会抛此错误。

 

posted on 2018-03-06 17:54  duanxz  阅读(34786)  评论(0编辑  收藏  举报