JVM優(yōu)化:虛擬機棧&本地方法棧
一、什么是虛擬機棧
Java虛擬機棧(Java Virtual Machine Stacks)也是線程私有的,即生命周期和線程相同。Java虛擬機棧和線程同時創(chuàng) 建,用于存儲棧幀。每個方法在執(zhí)行時都會創(chuàng)建一個棧幀(Stack Frame),用于存儲局部變量表、操作數(shù)棧、動態(tài) 鏈接、方法出口等信息。每一個方法從調(diào)用直到執(zhí)行完成的過程就對應(yīng)著一個棧幀在虛擬機棧中從入棧到出棧的過 程。

二、什么是棧幀
棧幀(Stack Frame)是用于支持虛擬機進行方法調(diào)用和方法執(zhí)行的數(shù)據(jù)結(jié)構(gòu)。棧幀存儲了方法的局部變量表、操作數(shù) 棧、動態(tài)連接和方法返回地址等信息。每一個方法從調(diào)用至執(zhí)行完成的過程,都對應(yīng)著一個棧幀在虛擬機棧里從入 棧到出棧的過程。


三、設(shè)置虛擬機棧的大小
Xss 為jvm啟動的每個線程分配的內(nèi)存大小,默認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)是一組變量值存儲空間,用于存放方法參數(shù)和方法內(nèi)定義的局部變量。包括8種基 本數(shù)據(jù)類型、對象引用(reference類型)和returnAddress類型(指向一條字節(jié)碼指令的地址)。 其中64位長度的long和double類型的數(shù)據(jù)會占用2個局部變量空間(Slot),其余的數(shù)據(jù)類型只占用1個。
五、操作數(shù)棧
操作數(shù)棧(Operand Stack)也稱作操作棧,是一個后入先出棧(LIFO)。隨著方法執(zhí)行和字節(jié)碼指令的執(zhí)行,會從局部 變量表或?qū)ο髮嵗淖侄沃袕?fù)制常量或變量寫入到操作數(shù)棧,再隨著計算的進行將棧中元素出棧到局部變量表或者 返回給方法調(diào)用者,也就是出棧/入棧操作。
六、動態(tài)鏈接
Java虛擬機棧中,每個棧幀都包含一個指向運行時常量池中該棧所屬方法的符號引用,持有這個引用的目的是為了 支持方法調(diào)用過程中的動態(tài)鏈接(Dynamic Linking)。
動態(tài)鏈接的作用:將符號引用轉(zhuǎn)換成直接引用。
七、方法返回地址
方法返回地址存放調(diào)用該方法的PC寄存器的值。一個方法的結(jié)束,有兩種方式:正常地執(zhí)行完成,出現(xiàn)未處理的異 常非正常的退出。無論通過哪種方式退出,在方法退出后都返回到該方法被調(diào)用的位置。方法正常退出時,調(diào)用者 的PC計數(shù)器的值作為返回地址,即調(diào)用該方法的指令的下一條指令的地址。而通過異常退出的,返回地址是要通過 異常表來確定,棧幀中一般不會保存這部分信息。 無論方法是否正常完成,都需要返回到方法被調(diào)用的位置,程序才能繼續(xù)進行。
八、本地方法棧
本地方法棧(Native Method Stacks) 與虛擬機棧所發(fā)揮的作用是非常相似的, 其區(qū)別只是虛擬機棧為虛擬機執(zhí)行 Java方法(也就是字節(jié)碼) 服務(wù), 而本地方法棧則是為虛擬機使用到的本地(Native) 方法服務(wù)。
特點
(1)本地方法棧加載native的但是方法, native類方法存在的意義當(dāng)然是填補java代碼不方便實現(xiàn)的缺陷而提出的。
(2)虛擬機棧為虛擬機執(zhí)行Java方法服務(wù),而本地方法棧則是為虛擬機使用到的Native方法服務(wù)。
(3)是線程私有的,它的生命周期與線程相同,每個線程都有一個。
在Java虛擬機規(guī)范中,對本地方法棧這塊區(qū)域,與Java虛擬機棧一樣,規(guī)定了兩種類型的異常:
(1)StackOverFlowError :線程請求的棧深度>所允許的深度。
(2)OutOfMemoryError:本地方法棧擴展時無法申請到足夠的內(nèi)存


























