OutOfMemoryError/OOM/內存溢出異常實例分析--虛擬機棧和本地方法棧溢出


關於虛擬機棧和本地方法棧,在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();
    }
}

參數設置如下:

我測了一下,系統差點卡死,就不展示測試結果了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM