本文部分摘自《深入理解 Java 虛擬機》
執行引擎
執行引擎是 Java 虛擬機核心的組成部分之一,作用就是用來執行位元組碼,在 Java 虛擬機規范中執行引擎只是一個概念模型,不同的虛擬機可以有不同的實作,通常會有解釋執行(通過編譯器執行)和編譯執行(通過即時編譯器產生本地代碼執行)兩種選擇,或者二者兼備,但無論是何種實作,從外觀上看,所有 Java 虛擬機的執行引擎的輸入、輸出都是一致的:輸入的是位元組碼的二進制流,處理程序是決議并執行位元組碼,輸出是執行結果
運行時堆疊幀結構
Java 虛擬機以方法作為最基本的執行單元,堆疊幀則是用于支持虛擬機進行方法呼叫和方法執行背后的資料結構,一個方法從呼叫開始至執行結束的程序,都對應一個堆疊幀在虛擬機堆疊里面從入堆疊到出堆疊的程序,

每一個堆疊幀到包括了區域變數表、運算元堆疊、動態連接、方法回傳地址和一些額外的附加資訊,下面將逐一做詳細介紹:
1. 區域變數表
區域變數表(Local Variables Table)是一組變數值的存盤空間,用于存放方法引數和方法內部定義的區域變數,在 Java 程式被編譯為 Class 檔案時,就在方法的 Code 屬性的 max_locals 資料項中確定了該方法所需分配的區域變數表的最大容量,
區域變數表的容量以變數槽(Variable Slot)為最小單位,Java 虛擬機規范中并沒有明確指出一個變數槽應占用的記憶體空間大小,對于 boolean、byte、char、short、int、float、reference 或 returnAddress 型別的資料,都可以使用 32 位或更小的物理記憶體來存盤,而對于 64 位的資料型別,如 long 和 double,Java 虛擬機會以高位對齊的方式為其分配兩個連續的變數槽空間,對于兩個相鄰的共同存放一個 64 位資料的變數槽,虛擬機不允許采用任何方式單獨訪問其中的某一個,
當一個方法被呼叫時,Java 虛擬機會使用區域變數表來完成引數值到引數變數串列的傳遞程序,即實參到形參的傳遞,如果執行的是實體方法,那區域變數表中第 0 位索引的變數槽默認是用于傳遞方法所屬物件實體的參考,通過關鍵字 this 來訪問這個隱含引數,其余引數則按照引數表順序排列,占用從 1 開始的區域變數槽,
為了盡可能節省堆疊幀所耗用的記憶體空間,區域變數表中的變數槽是可以重用的,方法體中定義的變數,其作用域并不一定會覆寫整個方法體,如果當前位元組碼 PC 計數器的值已經超過了某個變數的作用域,那這個變數對應的變數槽就可以交給其他變數重用,不過這種設計會伴隨有額外的副作用,例如在某些情況下變數槽的復用會直接影響到系統的垃圾收集行為
public static void main(String[] args) {
{
byte[] placeholder = new byte[64 * 1024 * 1024];
}
// int a = 0;
System.gc();
}
當執行到 System.gc() 時,雖然已經脫離 placeholder 的作用域,但由于變數槽還存在關于 placeholder 陣列物件的參考,所以不會被回收,如果我們把 int a = 0 這段注釋打開,那么原本 placeholder 對應的變數槽就會被其他變數復用,自然也就可以回收了,有時我們會看到手動將不再使用的變數置為 null 的操作,這并不見得是毫無意義的操作,可以將變數對應的區域變數槽清空,但在實際情況中,賦 null 值的操作在經過即時編譯優化后幾乎一定會被當成無效操作而被抹除,因此以恰當的變數作用域來控制變數的回收時間才是最優雅的解決手段,
2. 運算元堆疊
運算元堆疊(Operation Stack)是一個后進先出的堆疊結構,其最大深度也在編譯時就已確定,當一個方法剛開始執行時,這個方法的運算元堆疊是空的,在方法的執行程序中,會有各種位元組碼指令往運算元堆疊中寫入和提取內容,也就是入堆疊和出堆疊的操作,
3. 動態連接
每個堆疊幀都包含一個指向運行時常量池中該堆疊幀所屬的方法參考,持有這個參考是為了支持方法呼叫程序中的動態連接(Dynamic Linking),我們知道,在 Class 檔案的常量池中存在大量的符號參考,位元組碼中的方法呼叫指令就以常量池里指向的方法的符號參考作為引數,這些符號參考一部分會在類加載階段或者第一次使用時就被轉化為直接參考,稱為靜態決議,另外一部分將在每一次運行期間都轉化為直接參考,稱為動態連接,
4. 方法回傳地址
當一個方法開始執行后,只有兩種方式退出這個方法,要么正常結束,要么發生例外,無論采用何種退出方法的方式,都必須回傳最初方法呼叫的位置,程式才能繼續執行,一般來說,方法正常退出時,主調方法的 PC 計數器的值就可以作為回傳地址,在堆疊幀中保存,而方法例外退出,回傳地址是通過例外處理器表來確定的,堆疊幀一般不保存這個資訊,
5. 附加資訊
Java 虛擬機規范允許虛擬機實作增加一些規范里沒有描述的資訊到堆疊幀之中,例如與除錯、性能收集相關的資訊,這部分資訊完全取決于虛擬機的具體實作,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/251371.html
標籤:Java
下一篇:Spring整合MyBatis
