在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而已,所以不會拋此錯誤。