介紹
當啓動一個新線程時,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)
...