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