棧內(nèi)存溢出

計算機中每個操作系統(tǒng)給每個進程的內(nèi)存是有限制的(windows64位系統(tǒng)中最大分配內(nèi)存是2G),即對于虛擬機,最大內(nèi)存是2G,不算虛擬機進程啟動時所占用的內(nèi)存,剩下的內(nèi)存分配給共享區(qū)和線程獨享區(qū),共享區(qū)的內(nèi)存大小由虛擬機參數(shù)(-Xmx最大堆內(nèi)存,MaxPermSize最大方法區(qū)容量)指定,剩下的則分配給??臻g,程序計數(shù)器占用的空間極小可忽略不計,每個線程分配到的棧容量越大,可以建立的線程的數(shù)量自然就越少,建立線程時則更容易將內(nèi)存耗盡。
測試:

public class JavaVMStackSOF {

    private int stackLength = 1;

    public void stackLeak(){
        stackLength ++;
        stackLeak();
    }

    public static void main(String[] args) {
        JavaVMStackSOF oom = new JavaVMStackSOF();

        try {
            oom.stackLeak();
        }catch (Throwable e){
            System.out.println("stack length:" + oom.stackLength);
            throw e;
        }
    }
}

設置虛擬機參數(shù):
-Xss128k :設置每個線程的棧大小,減小這個值,可以使虛擬機創(chuàng)建更多線程
運行結果:

stack length:967
Exception in thread "main" java.lang.StackOverflowError
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:11)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
    at com.example.stackoverflowerror.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:12)
...

報出虛擬機棧超出虛擬機允許的最大深度的錯誤(StackOverflowError)。
通過-Xss控制了每個線程的最大棧大小,當棧不斷增大時,會暴露??臻g不足的錯誤,這種錯誤有兩種,一種是上述的棧深度超出,個人理解應該跟數(shù)組的outOfIndexError差不多的意思。
另一種就是虛擬機為棧分配的空間不足了,造成內(nèi)存溢出。
代碼:

public class JavaVMStackOOM {

    private void dontStop(){
        while (true){

        }
    }

    public void stackLeakByThread(){
        while (true){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();
                }
            });
            thread.start();
        }
    }

    public static void main(String[] args) {
        JavaVMStackOOM javaVMStackOOM = new JavaVMStackOOM();
        javaVMStackOOM.stackLeakByThread();
    }
}

設置虛擬機參數(shù):
-Xss2m 將每個線程分配的空間調(diào)大一些
由于java線程是映射到操作系統(tǒng)的內(nèi)核線程上的,因此上述代碼執(zhí)行有較大風險,可能會導致操作系統(tǒng)假死。本人測試的時候就死機了。。。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容