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