Java堆(Java Heap)
java堆是java虛擬機所管理的內(nèi)存中最大的一塊,是被所有線程共享的一塊內(nèi)存區(qū)域耘拇,在虛擬機啟動時創(chuàng)建撵颊。此內(nèi)存區(qū)域的唯一目的就是存放對象實例,這一點在Java虛擬機規(guī)范中的描述是:所有的對象實例以及數(shù)組都要在堆上分配惫叛。
java堆是垃圾收集器管理的主要區(qū)域秦驯,因此也被成為“GC堆”(Garbage Collected Heap)。從內(nèi)存回收角度來看java堆可分為:新生代和老生代(當(dāng)然還有更細(xì)致的劃分挣棕,在下一章會講到)译隘。從內(nèi)存分配的角度看,線程共享的Java堆中可能劃分出多個線程私有的分配緩沖區(qū)(Thread Local Allocation Buffer洛心,TLAB)固耘。無論怎么劃分,都與存放內(nèi)容無關(guān)词身,無論哪個區(qū)域厅目,存儲的都是對象實例,進一步的劃分都是為了更好的回收內(nèi)存法严,或者更快的分配內(nèi)存损敷。
根據(jù)Java虛擬機規(guī)范的規(guī)定,java堆可以處于物理上不連續(xù)的內(nèi)存空間中深啤。當(dāng)前主流的虛擬機都是可擴展的(通過 -Xmx 和 -Xms 控制)拗馒。如果堆中沒有內(nèi)存完成實例分配,并且堆也無法再擴展時溯街,將會拋出OutOfMemoryError異常诱桂。
Java虛擬機棧(Java Virtual Machine Stacks)
java虛擬機也是線程私有的,它的生命周期和線程相同呈昔。虛擬機棧描述的是Java方法執(zhí)行的內(nèi)存模型:每個方法在執(zhí)行的同時都會創(chuàng)建一個棧幀(Stack Frame)用于存儲局部變量表挥等、操作數(shù)棧、動態(tài)鏈接堤尾、方法出口等信息肝劲。
咱們常說的堆內(nèi)存、棧內(nèi)存中郭宝,棧內(nèi)存指的就是虛擬機棧辞槐。局部變量表存放了編譯期可知的各種基本數(shù)據(jù)類型(8個基本數(shù)據(jù)類型)、對象引用(地址指針)剩蟀、returnAddress類型催蝗。
局部變量表所需的內(nèi)存空間在編譯期間完成分配。在運行期間不會改變局部變量表的大小育特。
這個區(qū)域規(guī)定了兩種異常狀態(tài):如果線程請求的棧深度大于虛擬機所允許的深度,則拋出StackOverflowError異常;如果虛擬機楃衷可以動態(tài)擴展犬缨,在擴展是無法申請到足夠的內(nèi)存,就會拋出OutOfMemoryError異常棉浸。
本地方法棧(Native Method Stack)
本地方法棧與虛擬機棧所發(fā)揮作用非常相似怀薛,它們之間的區(qū)別不過是虛擬機棧為虛擬機執(zhí)行Java方法(也就是字節(jié)碼)服務(wù),而本地方法棧則為虛擬機使用到的native方法服務(wù)迷郑。本地方法棧也是拋出兩個異常枝恋。
方法區(qū)(Method Area)
方法區(qū)與java堆一樣,是各個線程共享的內(nèi)存區(qū)域嗡害,它用于存儲已被虛擬機加載的類信息焚碌、常量、靜態(tài)變量霸妹、即時編譯器編譯后的代碼等數(shù)據(jù)十电。它有個別命叫Non-Heap(非堆)。當(dāng)方法區(qū)無法滿足內(nèi)存分配需求時叹螟,拋出OutOfMemoryError異常鹃骂。
直接內(nèi)存(Direct Memory)
直接內(nèi)存不是虛擬機運行時數(shù)據(jù)區(qū)的一部分,也不是java虛擬機規(guī)范中定義的內(nèi)存區(qū)域罢绽。但這部分區(qū)域也唄頻繁使用畏线,而且也可能導(dǎo)致OutOfMemoryError異常
在JDK1.4中新加入的NIO(New Input/Output)類,引入了一種基于通道(Channel)與緩沖區(qū)(Buffer)的I/O方式良价,它可以使用Native函數(shù)庫直接分配堆外內(nèi)存象踊,然后通過一個存儲在java堆中的DirectByteBuffer對象作為這塊內(nèi)存的引用進行操作。
運行時常量池(Runtime Constant Pool)
運行時常量池是方法區(qū)的一部分棚壁。Class文件中除了有類的版本杯矩、字段、方法袖外、接口等描述信息外史隆,還有一項信息是常量池,用于存放編譯期生成的各種字面量和符號引用曼验,這部分內(nèi)容將在加載后進入方法區(qū)的運行時常量池中存放泌射。
程序計數(shù)器(Program Counter Register)
程序計數(shù)器是一塊較小的內(nèi)存空間,它可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號指示器鬓照。
由于Java虛擬機的多線程是通過線程輪流切換并分配處理器執(zhí)行時間的方式來實現(xiàn)的熔酷,一個處理器都只會執(zhí)行一條線程中的指令。因此豺裆,為了線程切換后能恢復(fù)到正確的執(zhí)行位置拒秘,每條線程都有一個獨立的程序計數(shù)器号显,各個線程之間計數(shù)器互不影響,獨立存儲躺酒。稱之為“線程私有”的內(nèi)存押蚤。程序計數(shù)器內(nèi)存區(qū)域是虛擬機中唯一沒有規(guī)定OutOfMemoryError情況的區(qū)域。
執(zhí)行引擎
虛擬機核心的組件就是執(zhí)行引擎羹应,它負(fù)責(zé)執(zhí)行虛擬機的字節(jié)碼揽碘,一般戶先進行編譯成機器碼后執(zhí)行.
垃圾收集系統(tǒng)
垃圾收集系統(tǒng)是Java的核心,也是不可少的园匹,Java有一套自己進行垃圾清理的機制雳刺,開發(fā)人員無需手工清理