JVM 棧(stack)溢出案例

介紹

當啓動一個新線程時,JVM就會給這個線程分配一個Java棧(這個棧的內存大小由-Xss參數來設置)。

一個Java棧的基本單位是幀,每一次函數調用就會生成棧幀,佔用一定的棧空間。當函數本身需要的內存過大,或者函數調用函數(依賴調用或者遞歸調用)太深,超過了-Xss設置的內存大小,就會拋出StackOverflowError異常。

-Xss:默認值 1M,控制每個線程佔用的內存,這個參數決定了函數調用的最大深度。如果設置的太小可能會很容易出現 StackOverflowError 異常。

JDK 5.0以後每個線程堆棧大小爲1M,以前每個線程堆棧大小爲256K。在相同物理內存下,減小這個值能生成更多的線程。但是操作系統對一個進程內的線程數還是有限制的,不能無限生成,經驗值在3000~5000左右。

示例代碼

public class StackOverflow {

    private static int deep = 1;

    /**
     * 通過無限遞歸來模擬棧溢出
     */
    private static void recursion() {
        deep++;
        recursion();
    }

    public static void main(String[] args) {
        try {
            recursion();
        } catch (Throwable e) { // catch 捕獲的是 Throwable,而不是 Exception。因爲 StackOverflowError 不屬於 Exception 的子類。
            System.out.println("Stack deep : " + deep);
            e.printStackTrace();
        }

        // 不讓進程結束,便於使用分析工具來查看內存情況
        try {
            Thread.sleep(24 * 60 * 60 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

執行結果

Stack deep : 11429
java.lang.StackOverflowError
    at com.song.StackOverflow.call(StackOverflow.java:16)
    at com.song.StackOverflow.call(StackOverflow.java:17)
    ...
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章