關於虛擬機棧和本地方法棧,在JVM規范中描述了兩種異常:
1.如果線程請求的棧深度大於JVM所允許的深度,將拋出StackOverflowError異常;
2.如果虛擬機在擴展棧時無法申請到足夠的內存,就會拋出OutOfMemoryError異常。
下面進行虛擬機棧和本地方法棧的SOF異常測試:
public class JavaVMStackSOF { private int stackLenth = 1; public void stackLeak() { stackLenth++; stackLeak(); } public static void main(String[] args) throws Throwable{ JavaVMStackSOF oom = new JavaVMStackSOF(); try { oom.stackLeak(); } catch (Throwable e) { System.out.println("棧深度:" + oom.stackLenth); throw e; } } }
運行時設置棧容量為:-Xss128k
具體操作可參照:OutOfMemoryError/OOM/內存溢出異常實例分析--堆內存溢出
運行結果如下:
實驗結果表明:在單線程下,無論是 由於棧幀太大還是虛擬機棧容量太小,當內存無法分配的時候,虛擬機棧跑出的都是StackOverflowError異常。
怎么產生OOM異常呢?
可以通過不斷創建線程的方法,在這種情況下,為每個線程分配的內存越大,就會越容易產生OOM異常。
下面在測試之前,先特別提示一下,如果想測試棧的OOM異常,記得先保存當前的工作。由於Windows平台的虛擬機中,Java的線程是映射到操作
系統的內核上的,因此以下代碼可能會導致操作系統假死
public class JavaVMStackOOM { private void dontStop() { while (true) { } } public void stackLeakByThread() { while (true) { new Thread(new Runnable() { @Override public void run() { dontStop(); } }).start(); } } public static void main(String[] args) { JavaVMStackOOM oom = new JavaVMStackOOM(); oom.stackLeakByThread(); } }
參數設置如下:
我測了一下,系統差點卡死,就不展示測試結果了