文章福利:阿里巴巴編碼規范-各版本下載
每一個方法的運行都伴隨著堆疊幀的入堆疊到出堆疊程序,那么堆疊幀中有什么呢?
既然每個方法都被映射成一個個堆疊幀,方法中有什么則堆疊幀中或多或少都應該也有什么吧,思路是沒問題的,
方法中有什么呢?
如下是一個很普通的方法:
public String test(String a, Integer b){
int c = 0;
int d = c + b;
return a;
}
該方法中包含如下資訊:
-
方法引數a 和 b;
-
區域變數c 和 d;
-
回傳值 a;
-
其他隱藏資訊;
堆疊幀中有什么呢?
對比上述方法中包含的資訊,那么堆疊幀中應當有存盤方法里的引數、區域變數、回傳值等資訊的資料結構及其他細節資訊,答案是肯定的,
明白了堆疊幀的設計是為了運行時方法資訊的存盤,下面就來看看堆疊幀中具體包含那些資訊
一個堆疊幀中應當包含以下資訊:
區域變數表、運算元堆疊、動態鏈接、回傳值資訊和其他資訊,

本篇暫不打算說堆疊幀中的的區域變數表等資訊,本篇和小伙伴們大致學習了解下對堆疊幀的初步印象,
關于堆疊幀的其他重要資訊
當一個執行緒中的方法呼叫鏈很長的時候,其對應的堆疊幀數量也就很多,每個堆疊幀都占有一定大小的空間,在代碼編譯期每個方法對應的堆疊幀大小就已經確定,而虛擬機堆疊的大小是不確定的,一般一個執行緒堆疊默認大小為1MB,可以修改該值,
這里一定要注意,編譯期只是確定了堆疊幀中需要多大的變數表,而程式運行后需要多大的虛擬機堆疊記憶體是不知道的,這樣就會出現一種問題:
不正確的遞回呼叫會導致堆疊記憶體溢位(stackoverflow),因為不正確的使用遞回,運行期間遞回方法一直在回圈呼叫,每個占用的堆疊幀空間一直沒有被釋放,呼叫次數到達虛擬機堆疊記憶體的最大記憶體后就會出現堆疊溢位的情況,
遞回導致堆疊溢位演示:
public class JVMTes {
private int stackDepth = 0;
public void test(){
stackDepth++;
test();
}
public static void main(String[] args) {
JVMTes jvmTes = new JVMTes();
try {
jvmTes.test();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("呼叫次數:" + jvmTes.stackDepth);
}
}
}
運行結果:
呼叫次數:995
Exception in thread "main" java.lang.StackOverflowError
at main.java.jvm.JVMTes.test(JVMTes.java:8)
at main.java.jvm.JVMTes.test(JVMTes.java:9)
at main.java.jvm.JVMTes.test(JVMTes.java:9)
at main.java.jvm.JVMTes.test(JVMTes.java:9)
at main.java.jvm.JVMTes.test(JVMTes.java:9)
Process finished with exit code 1
堆疊的OOM情況
若虛擬機堆疊有一個動態擴展記憶體機制,執行緒申請的堆疊記憶體空間大于預設值,先去動態擴展記憶體,若擴展后還是不夠執行緒申請的堆疊記憶體大小,此時就會記憶體溢位
然而,堆疊的OOM情況有些虛擬機是沒有實作的,比如我們常見的HotSpot
附:Java虛擬機規范關于堆疊的例外:
-
若執行緒請求的堆疊深度大于虛擬機所允許的最大深度,將拋出StackOverflowError例外
-
若虛擬機的堆疊記憶體允許動態擴展,當擴展堆疊容量無法申請到足夠的記憶體時,將拋出 OutOfMemoryError例外
--- END ---
關注公眾號 Java島 ,每天進步億點點,和小編一起成長Java呀!

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/298469.html
標籤:其他
上一篇:【Java 虛擬機原理】Java 類加載程序 ( 加載 | 連接 - 驗證 準備 決議 | 初始化 | 使用 | 卸載 )
