JVM結(jié)構(gòu)體系
jvm由`類加載器子系統(tǒng)`、`運(yùn)行時(shí)數(shù)據(jù)區(qū)`(內(nèi)存空間)、`執(zhí)行引擎`及`本地方法接口`等組成
`運(yùn)行時(shí)數(shù)據(jù)區(qū):`由方法區(qū)、堆、java 棧、PC寄存器、本地方法棧組成
在內(nèi)存空間中方法區(qū)和堆是所有java線程共享的,而java棧、本地方法棧、PC寄存器則有每個(gè)線程私有
程序計(jì)數(shù)器(program counter register)
它是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器
字節(jié)碼解釋器通過改變程序計(jì)數(shù)器的值來選擇下一條需要執(zhí)行的字節(jié)碼指令,分支、跳轉(zhuǎn)、循環(huán)等基礎(chǔ)功能都需要依賴它來實(shí)現(xiàn),所以程序計(jì)數(shù)器是線程私有的,各線程間的計(jì)數(shù)器互不影響
當(dāng)線程在執(zhí)行一個(gè)java方法時(shí)(非本地方法),該計(jì)數(shù)器記錄的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的地址,當(dāng)線程在執(zhí)行的是native方法時(shí),該計(jì)數(shù)器的值為空。唯一在java虛擬機(jī)規(guī)范中沒有OOM的區(qū)域
Java虛擬機(jī)棧(java stacks)
線程私有,保證線程安全,生命周期與線程相同
java棧由棧幀組成,每個(gè)方法被執(zhí)行的時(shí)候都會(huì)同時(shí)創(chuàng)建一個(gè)棧幀,調(diào)用方法時(shí)壓入棧幀,方法返回時(shí)彈出棧幀并拋棄
先進(jìn)后出
對于執(zhí)行引擎來說,活動(dòng)線程中只有棧頂?shù)臈怯行У模瑘?zhí)行引擎所運(yùn)行的所有字節(jié)碼指令都只針對當(dāng)前棧幀進(jìn)行操作
java棧的主要任務(wù)是儲(chǔ)存方法參數(shù)、局部變量、中間運(yùn)算結(jié)果,并且提供部分其他模塊工作需要的數(shù)據(jù)
在編譯程序代碼時(shí),棧幀中需要多大的局部變量表、多深的操作數(shù)棧都已經(jīng)完全確定來,并且寫入了方法表的code屬性之中所以程序運(yùn)行期變量數(shù)據(jù)不會(huì)影響棧幀內(nèi)存大小,僅僅取決于具體的虛擬機(jī)實(shí)現(xiàn)。
在java虛擬機(jī)規(guī)范中,棧會(huì)拋出2種異常情況
- 1、如果
線程請求的棧深度大于虛擬機(jī)所允許的深度,將拋出StackOverFlowerError異常 - 2、如果虛擬機(jī)在動(dòng)態(tài)擴(kuò)展棧時(shí)
無法申請到足夠的內(nèi)存空間,則拋出OutOfMemoryError異常
本地方法棧(native method stacks)
與java棧作用類似,java棧為虛擬機(jī)執(zhí)行java方法服務(wù),本地方法棧則為使用到的本地操作系統(tǒng)(native)方法服務(wù)
Java堆(Heap)
堆是所有線程共享的一塊內(nèi)存區(qū)域。幾乎所有的對象實(shí)例和數(shù)組都在這類分配內(nèi)存
java堆可以處理在物理上不連續(xù)的內(nèi)存空間 中 ,只要是邏輯上是連續(xù)就可以
如果在堆中沒有內(nèi)存可分配時(shí),并且堆也無法擴(kuò)展時(shí),將會(huì)拋出OutOfMemoryError異常
方法區(qū)(method area)
各個(gè)線程共享的內(nèi)存區(qū)域
用于存儲(chǔ)已經(jīng)被虛擬機(jī)加載的類信息、常量、靜態(tài)常量 ,即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。和java heap一樣不需要連續(xù)的內(nèi)存,可以選擇固定大小或可擴(kuò)展
虛擬機(jī)規(guī)范允許該區(qū)域可以選擇不實(shí)現(xiàn)垃圾回收
根據(jù)java虛擬機(jī)規(guī)范,當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時(shí),將拋出OutOfMemoryError異常
類加載機(jī)制
類的整個(gè)生命周期包括:加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用和卸載七個(gè)階段
類加載的過程包括了:加載->驗(yàn)證->準(zhǔn)備 ->解析-> 初始化
按順序開始,而不是按順序進(jìn)行或完成,通常都是互相交叉地混合進(jìn)行,在一個(gè)階段執(zhí)行的過程中調(diào)用或激活另一個(gè)階段