JVM 棧(stack)溢出案例

介紹

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

一個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)
    ...
相關文章
相關標籤/搜索