JVM優化:虛擬機棧&本地方法棧
一、什么是虛擬機棧
Java虛擬機棧(Java Virtual Machine Stacks)也是線程私有的,即生命周期和線程相同。Java虛擬機棧和線程同時創 建,用于存儲棧幀。每個方法在執行時都會創建一個棧幀(Stack Frame),用于存儲局部變量表、操作數棧、動態 鏈接、方法出口等信息。每一個方法從調用直到執行完成的過程就對應著一個棧幀在虛擬機棧中從入棧到出棧的過 程。
二、什么是棧幀
棧幀(Stack Frame)是用于支持虛擬機進行方法調用和方法執行的數據結構。棧幀存儲了方法的局部變量表、操作數 棧、動態連接和方法返回地址等信息。每一個方法從調用至執行完成的過程,都對應著一個棧幀在虛擬機棧里從入 棧到出棧的過程。
三、設置虛擬機棧的大小
Xss 為jvm啟動的每個線程分配的內存大小,默認JDK1.4中是256K,JDK1.5+中是1M
- Linux/x64 (64-bit): 1024 KB
- macOS (64-bit): 1024 KB
- Oracle Solaris/x64 (64-bit): 1024 KB
- Windows: The default value depends on virtual memory
-Xss1m
-Xss1024k
-Xss1048576
四、局部變量表
局部變量表(Local Variable Table)是一組變量值存儲空間,用于存放方法參數和方法內定義的局部變量。包括8種基 本數據類型、對象引用(reference類型)和returnAddress類型(指向一條字節碼指令的地址)。 其中64位長度的long和double類型的數據會占用2個局部變量空間(Slot),其余的數據類型只占用1個。
五、操作數棧
操作數棧(Operand Stack)也稱作操作棧,是一個后入先出棧(LIFO)。隨著方法執行和字節碼指令的執行,會從局部 變量表或對象實例的字段中復制常量或變量寫入到操作數棧,再隨著計算的進行將棧中元素出棧到局部變量表或者 返回給方法調用者,也就是出棧/入棧操作。
六、動態鏈接
Java虛擬機棧中,每個棧幀都包含一個指向運行時常量池中該棧所屬方法的符號引用,持有這個引用的目的是為了 支持方法調用過程中的動態鏈接(Dynamic Linking)。
動態鏈接的作用:將符號引用轉換成直接引用。
七、方法返回地址
方法返回地址存放調用該方法的PC寄存器的值。一個方法的結束,有兩種方式:正常地執行完成,出現未處理的異 常非正常的退出。無論通過哪種方式退出,在方法退出后都返回到該方法被調用的位置。方法正常退出時,調用者 的PC計數器的值作為返回地址,即調用該方法的指令的下一條指令的地址。而通過異常退出的,返回地址是要通過 異常表來確定,棧幀中一般不會保存這部分信息。 無論方法是否正常完成,都需要返回到方法被調用的位置,程序才能繼續進行。
八、本地方法棧
本地方法棧(Native Method Stacks) 與虛擬機棧所發揮的作用是非常相似的, 其區別只是虛擬機棧為虛擬機執行 Java方法(也就是字節碼) 服務, 而本地方法棧則是為虛擬機使用到的本地(Native) 方法服務。
特點
(1)本地方法棧加載native的但是方法, native類方法存在的意義當然是填補java代碼不方便實現的缺陷而提出的。
(2)虛擬機棧為虛擬機執行Java方法服務,而本地方法棧則是為虛擬機使用到的Native方法服務。
(3)是線程私有的,它的生命周期與線程相同,每個線程都有一個。
在Java虛擬機規范中,對本地方法棧這塊區域,與Java虛擬機棧一樣,規定了兩種類型的異常:
(1)StackOverFlowError :線程請求的棧深度>所允許的深度。
(2)OutOfMemoryError:本地方法棧擴展時無法申請到足夠的內存