程序計數(shù)器:是線程私有的黑低,是一塊較小的內(nèi)存空間,當前線程所執(zhí)行的字節(jié)碼的行號指示器。JAVA虛擬機的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)浪蹂。在任何一個確定的時刻,一個處理器都只會執(zhí)行一條線程中的指令告材。因此坤次,為了線程切換后能恢復(fù)到正確的執(zhí)行位置,每條線程都需要一個獨立的程序計數(shù)器斥赋,各個線程之間計數(shù)器互不影響缰猴,獨立存儲。沒有規(guī)范OutOfMemoryError情況的區(qū)域疤剑。
虛擬機棧:也是線程私有的滑绒。描述的是JAVA方法執(zhí)行的內(nèi)存模型闷堡。每個方法執(zhí)行時都會創(chuàng)建一個棧幀,用于存儲局部變量表疑故、操作數(shù)棧杠览、動態(tài)鏈接、方法出口等信息纵势。每一個方法從調(diào)用直至執(zhí)行完成的過程倦零,就對應(yīng)著一個棧幀一個棧幀出棧到入棧的過程。異常規(guī)范:如果線程請求的棧深度大于虛擬機棧所允許的深度吨悍,將拋出Stack OverflowError異常扫茅;如果虛擬機棧可以動態(tài)擴展育瓜,如果擴展無法申請到足夠的內(nèi)存葫隙,就會拋出OutOfMemoryError異常。下圖展示了虛擬機棧壓棧的示例躏仇。
本地方法棧:線程私有恋脚,本地方法棧與虛擬機棧所發(fā)揮的作用是非常相似的,區(qū)別是虛擬機棧為虛擬機執(zhí)行JAVA方法服務(wù)焰手,而本地方法棧則為虛擬機使用的native方法服務(wù)糟描。也會拋出StackOverFlowError和OutOfMemoryError異常。
JAVA堆:JAVA堆是被所有線程共享的一塊內(nèi)存區(qū)域书妻,在虛擬機啟動時創(chuàng)建時船响。此內(nèi)存區(qū)域的唯一目的就是存放對象實例。但是隨著JIT編譯器的發(fā)展與逃逸分析技術(shù)逐漸成熟躲履,棧上分配见间、標量替換優(yōu)化技術(shù)的變化,在堆上分配變得不那么絕對了工猜。JAVA堆是垃圾收集器管理的主要區(qū)域米诉。從內(nèi)存回收的角度來看,由于現(xiàn)在收集器基本都采用分代收集算法篷帅,所以JAVA堆可以細分為:新生代和老年代史侣,在細致一點可以分為Eden區(qū)、From Survivor空間魏身、To Survivor空間惊橱。從內(nèi)存分配角度看,線程共享的JAVA堆中可能劃分出多個線程私有的分配緩沖區(qū)(Thread Local Allocation Buffer叠骑,TLAB)李皇。
方法區(qū):與JAVA堆一樣是各個線程共享的內(nèi)存區(qū)域削茁,它用于存儲已被虛擬機加載的類信息宙枷、常量掉房、靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù)慰丛。該區(qū)域在HotSpot虛擬機中也可稱為永久代卓囚,該稱為只是為了將該區(qū)域納入到GC收集中去,在其他虛擬機中并沒有這樣定義诅病。
什么是運行時常量池哪亿?
運行時常量池是方法區(qū)的一部分,Class文件中除了有類的版本贤笆、字段蝇棉、方法、接口等描述信息外還有一項信息就是常量池芥永,用于存放編譯期生成的各種字面量和符號引用篡殷,這部分內(nèi)容將在類加載后進入方法區(qū)的運行時常量池中存放。運行時常量池相對于Class文件常量池的另外一個重要特征是具備動態(tài)性埋涧,JAVA語言并不要求常量一定只有在編譯期才能產(chǎn)生板辽,運行期間也可能將新的常量放入到池中,利用的比較多的是String類的intern()方法棘催。
什么是直接內(nèi)存劲弦?
直接內(nèi)存并不是虛擬機運行時數(shù)據(jù)區(qū)的一部分,也不是JAVA虛擬機規(guī)范中定義的內(nèi)存區(qū)域醇坝,在JDK1.4中新加入了NIO類邑跪,引入了一種基于通道(Channel)和緩沖區(qū)(Buffer)的I/O方式,他可以使用Native函數(shù)庫直接分配堆外內(nèi)存呼猪,然后通過一個存儲在JAVA堆中的DirectByteBuffer對象作為這塊內(nèi)存的引用進行操作呀袱。