###jvm運行時數(shù)據(jù)區(qū)域(NO.1)
>
>(img)
>(img)
##程序計數(shù)器
>程序計數(shù)器在jvm中是一個邏輯上的概念腊徙,在內(nèi)存中,每個線程都擁有一塊獨立的內(nèi)存空間來存儲執(zhí)行位置爽室,是線程私有的硫嘶。java多線程是通過線程輪流切換來分配處理器執(zhí)行時間的
>如果正在執(zhí)行的是java方法蠢琳,那么這個計數(shù)器記錄的就是正在執(zhí)行的虛擬機字節(jié)碼指令的地址;如果正在執(zhí)行的是Native方法辈灼,那么這個計數(shù)器值則為空(Undefined),該與其是唯一一個在Java虛擬機規(guī)范中沒有規(guī)定任何OutOfMemoryError情況的區(qū)域也榄。
> **Q:Java多線程執(zhí)行native方法時程序計數(shù)器為空巡莹,那么線程切換后如何找到之前執(zhí)行到哪里了? **
> A:這里的“pc寄存器”是在抽象的JVM層面上的概念——當(dāng)執(zhí)行Java方法時甜紫,這個抽象的“pc寄存器”存的是Java字節(jié)碼的地址降宅。實現(xiàn)上可能有兩種形式,一種是相對該方法字節(jié)碼開始處的偏移量囚霸,叫做bytecode index钉鸯,簡稱bci;另一種是該Java字節(jié)碼指令在內(nèi)存里的地址邮辽,叫做bytecode pointer唠雕,簡稱bcp。對native方法而言吨述,它的方法體并不是由Java字節(jié)碼構(gòu)成的岩睁,自然無法應(yīng)用上述的“Java字節(jié)碼地址”的概念。所以JVM規(guī)范規(guī)定揣云,如果當(dāng)前執(zhí)行的方法是native的捕儒,那么pc寄存器的值未定義——是什么值都可以。上面是JVM規(guī)范所定義的抽象概念,那么實際實現(xiàn)呢刘莹?Java線程總是需要以某種形式映射到OS線程上阎毅。映射模型可以是1:1(原生線程模型)、n:1(綠色線程 / 用戶態(tài)線程模型)点弯、m:n(混合模型)扇调。以HotSpot VM的實現(xiàn)為例,它目前在大多數(shù)平臺上都使用1:1模型抢肛,也就是每個Java線程都直接映射到一個OS線程上執(zhí)行狼钮。此時,native方法就由原生平臺直接執(zhí)行捡絮,并不需要理會抽象的JVM層面上的“pc寄存器”概念——原生的CPU上真正的PC寄存器是怎樣就是怎樣熬芜。就像一個用C或C\+\+寫的多線程程序,它在線程切換的時候是怎樣的福稳,Java的native方法也就是怎樣的涎拉。
##虛擬機棧
>每個線程在創(chuàng)建自己的時候都擁有一個私有的虛擬機棧,棧幀(Stack Frame)是虛擬機棧的棧元素的圆。_由于棧的數(shù)據(jù)結(jié)構(gòu)(先進后出)非常符合方法調(diào)用的邏輯曼库,所以使用了棧這種邏輯結(jié)構(gòu)。_
>java虛擬機棧的生命周期是與線程的生命周期相同的略板,每一個方法從調(diào)用到執(zhí)行完成的過程就是虛擬機棧從入棧到出棧的過程毁枯。虛擬機棧中的局部變量表部分所需的內(nèi)存空間在編譯器就完成分配了,在方法運行期間是不會改變局部變量表的大小叮称。
>兩種異常:如果線程請求的棧深度大于虛擬機所允許的深度种玛,將拋出StackOverflowError異常,如果虛擬機椚块埽可以動態(tài)擴展(大部分虛擬機都可以擴展赂韵,且是默認配置,也允許固定)挠蛉,如果擴展時申請不到足夠的內(nèi)存時則會拋出OutOfMemoryError異常祭示。
##本地方法棧
>本地方法棧和虛擬機棧相同,HotSpot虛擬機將兩者合二為一谴古,也會拋出StackOverflowError和OutOfMemoryError異常
##java堆
>java堆是線程共享的一塊區(qū)域质涛,所有的對象實例以及數(shù)組都要在堆上分配(現(xiàn)在的JVM不是絕對的)也是GC管理的主要區(qū)域,可以擴展通過-Xmx和-Xms控制掰担,當(dāng)堆中沒有內(nèi)存完成實例分配汇陆,并且堆也無法再擴展時,將會拋出OutOfMemoryError異常带饱。
##方法區(qū)
>與java堆一樣毡代,屬于線程共享的區(qū)域阅羹,用于存儲已被虛擬機加載的類的信息、常量教寂、靜態(tài)變量捏鱼、即時編譯器遍以后的代碼等數(shù)據(jù),Non-heap
##運行時常量區(qū) (Runtime Constant Pool)
>是方法區(qū)的一部分酪耕,用于存放編譯期生成的各種字面量和符號引用导梆,這部分內(nèi)容將在類加載后進入方法去的運行時常量池中存放。除了Class文件中的符號引用外因妇,還會把翻譯出來的直接引用也存儲在運行時常量池中问潭。
##直接內(nèi)存(Direct Memory)
>不是java虛擬機的內(nèi)存部分猿诸,但也可能導(dǎo)致OutOfMemoryError,例如NIO會直接分配堆外內(nèi)存,但是本機的直接內(nèi)存分配不會受到j(luò)ava堆大小的限制,需要注意的是設(shè)置參數(shù)的時候燎竖,不要使得總內(nèi)存大于物理內(nèi)存限制(硬件和操作系統(tǒng)的限制)