JVM 規格定義的是抽象執行模型,而不是作業系統的記憶體配置圖。實作可以使用 JIT 編譯、移動式垃圾收集、連續或分段儲存,以及原生中繼資料,同時保留規格所定義的行為。
執行期資料區域 #
每個 JVM 執行緒都有程式計數器暫存器、JVM 堆疊,以及可選的原生方法堆疊。對 Java 程式碼而言,PC 會識別目前的 JVM 指令;執行原生程式碼時,PC 的值未定義。JVM 堆疊保存框架;建立框架失敗時,若原因是大小限制則產生 StackOverflowError,若可擴充的堆疊無法成長則產生 OutOfMemoryError。
Heap 是共用的,並包含物件與陣列。方法區域是共用的,保存每個類別的結構;其具體位置(例如 HotSpot metaspace)取決於實作。每個類別或介面都有執行期常數池,這是其類別檔常數與符號參照的執行期形式。這些共用區域會透過類別載入觸及,且與執行緒的框架分開。
框架與執行 #
每次方法呼叫都會建立框架,其中包含區域變數陣列、運算元堆疊、目前類別執行期常數池的參照,以及回傳或例外完成狀態。類別檔的 max_locals 與 max_stack 會限制前兩個區域。位元組碼會在區域變數與運算元堆疊之間移動值;呼叫指令會解析符號參照,並將控制權轉移至新框架。正常完成時,結果會回傳至呼叫者的運算元堆疊;異常完成時,VM 會在展開堆疊的同時搜尋例外處理常式。
類別載入器提供類別檔位元組並建立型別識別。執行引擎會驗證、直譯並可能編譯位元組碼;它不是類別載入器。JVMS 以載入、連結、初始化與指令執行來規定兩者的界線,而不是指定引擎架構。
布林值與結束 #
JVM 沒有專用的布林算術指令。Java 編譯器會使用 int 計算值處理布林運算式,而 boolean 陣列會使用 baload 與 bastore 存取;規格要求其儲存編碼使用 0 表示 false、1 表示 true。不要從位元組碼慣例推論 Java 物件欄位配置。
Java 應用程式通常會在最後一個非 daemon 執行緒結束時終止。System.exit 會透過執行期要求 VM 終止,而單一執行緒未復原的失敗不會終止其他非 daemon 執行緒。原生程式碼、關閉 Hook 與主機程序都可能影響觀察到的關閉行為。
評論
在 GitHub 上閱讀或評論(發表評論需要登入)