Java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)域匯總
程序計(jì)數(shù)器(Program Counter)
程序計(jì)數(shù)器作為一個(gè)概念模型,這個(gè)是用來(lái)指示下一條需要執(zhí)行的字節(jié)碼指令在哪。
Java的多線程實(shí)際上是通過(guò)線程輪轉(zhuǎn)做到的,如果是一個(gè)單核的機(jī)器(或單cpu),嚴(yán)格意義上在一個(gè)時(shí)間塊中只會(huì)有一個(gè)線程在執(zhí)行。為了線程切換以后能恢復(fù)到正確的執(zhí)行位置,每個(gè)線程都需要有一個(gè)單獨(dú)的計(jì)數(shù)器,每個(gè)計(jì)數(shù)器之間要是獨(dú)立的互不干擾。

如果線程執(zhí)行的是Java方法,那么PC指向的是正在執(zhí)行的虛擬機(jī)字節(jié)碼指令的區(qū)域,如果執(zhí)行的是native方法,那么它是undefined。
Java虛擬機(jī)棧
Java virtue machine也是線程私有的,它擁有一個(gè)和線程相同的生命周期
虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型;stack frame(棧幀)是一個(gè)經(jīng)常談及的概念,它用來(lái)儲(chǔ)存內(nèi)部變量表,操作數(shù)棧,動(dòng)態(tài)鏈接,方法出口等等。
每一個(gè)方法從調(diào)用到執(zhí)行完畢,也就對(duì)應(yīng)著一個(gè)棧幀在虛擬機(jī)棧中的入棧和出棧
我們以前畫(huà)圖來(lái)說(shuō)明內(nèi)存區(qū)的時(shí)候,總是去關(guān)注Heap(堆內(nèi)存)和stack(棧內(nèi)存)這兩部分,這是與對(duì)象內(nèi)存分配最相關(guān)的兩塊內(nèi)存區(qū)。通常所說(shuō)的stack就是虛擬機(jī)棧,或者更具體的說(shuō)是虛擬機(jī)棧中的局部變量表。
局部變量表存放了編譯器可知的各種基本數(shù)據(jù)類型(boolean byte double char int short long float)對(duì)象引用(reference類型,并不是對(duì)象本身,可能是地址的引用指針,也可能是一個(gè)代代表對(duì)象的句柄)return address類型(指向一條字節(jié)碼指令的地址)
局部變量表的意義就在于,可以把表所需的內(nèi)存在編譯器就進(jìn)行分配,每次程序去調(diào)用一個(gè)方法的時(shí)候,方法需要在frame中分配多少的局部?jī)?nèi)存空間是確定的。
兩種異常情況
如果線程請(qǐng)求的棧的深度大于虛擬機(jī)所允許的,就是StackOverFlowError,如果是支持動(dòng)態(tài)拓展的虛擬機(jī)(大部分的現(xiàn)代虛擬機(jī)都支持)依然無(wú)法申請(qǐng)到足夠的內(nèi)存,就會(huì)報(bào)出OutOfMemoryError異常。
本地方法棧
本地方法棧是和Java虛擬機(jī)棧對(duì)應(yīng)的一個(gè)概念,它們的作用也是相近的,唯一的不同是,本地方法棧執(zhí)行的是native方法,而Java虛擬機(jī)棧執(zhí)行的是Java方法(也就是字節(jié)碼)服務(wù)
在Sun的HotSpot虛擬機(jī)里面,本地方法棧和虛擬機(jī)棧是一個(gè)。
Java堆
堆是被所有的線程所共享的一塊區(qū)域,這塊內(nèi)存區(qū)域存在的唯一目的就是存放對(duì)象實(shí)例,在虛擬機(jī)啟動(dòng)的時(shí)候就會(huì)被創(chuàng)建,幾乎所有的對(duì)象實(shí)例都會(huì)在這里被分配內(nèi)存
所有的對(duì)象實(shí)例和數(shù)組都要在堆上分配 --《Java虛擬機(jī)規(guī)范》
隨著JIT編譯器的發(fā)展和逃逸技術(shù)的成熟,這句話也變得不是那么的絕對(duì)了。
GC(garbage collection)也發(fā)生在這個(gè)區(qū)域,所以有時(shí)候也被稱為GC堆
方法區(qū)
方法區(qū)和Java堆相似,是線程共享的一段內(nèi)存區(qū)域,它用于儲(chǔ)存已經(jīng)被虛擬機(jī)加載的類信息,常量,靜態(tài)變量,即時(shí)編譯器編譯后的代碼。
聽(tīng)起來(lái)好像和Java堆很像,Java虛擬機(jī)標(biāo)準(zhǔn)里面也把它視為堆的一個(gè)邏輯部分,但是它被稱作Non-Heap,目的是和Java堆區(qū)分開(kāi)來(lái)。
Permanent Generation?那么,這個(gè)方法區(qū)就是永久代嗎,并不是。只是在HotSpot虛擬機(jī)的設(shè)計(jì)中,用永久代來(lái)實(shí)現(xiàn)了方法區(qū)。(在JDK1.7中,已經(jīng)把原本放在永久代的字符串常量池移出了)
運(yùn)行時(shí)常量池(Runtime Constant Pool)
這也是方法區(qū)的一個(gè)較重要的部分,.class文件除了有類的版本,字段,方法,接口等描述信息外,還有一部分是常量池,用于在存放編譯期生成的各種字面量(Literal)和符號(hào)引用(Symbolic References),這部分的內(nèi)容在類加載以后進(jìn)入運(yùn)行時(shí)常量池中存放。
字面量比較好理解,是Java語(yǔ)言層面的常量,例如文本字符串,聲明為final的變量
符號(hào)引用這個(gè)我第一時(shí)間沒(méi)看懂什么意思,其實(shí)是編譯原理的一個(gè)概念,包括以下的三種常量:
- 類和接口的全限定名
- 字段名稱和描述符
- 方法名稱和描述符
動(dòng)態(tài)性,這是運(yùn)行時(shí)常量池的一個(gè)重要的特性,在運(yùn)行期間也可以將新的常量放進(jìn)常量區(qū)(包括基本包裝類和String,也可以調(diào)用intern()將String強(qiáng)制放進(jìn)常量池)
為什么需要運(yùn)行時(shí)常量池呢?
- 更少的內(nèi)存。直接賦值的時(shí)候會(huì)利用常量池里面的對(duì)象,而不是去new了一個(gè)
- 更快的速度 ?!?='比equals()更快
Integer a = 23;//在編譯的時(shí)候會(huì)變成Integer i1=Integer.valueOf(40);使用的是線程池里面的對(duì)象 Integer b = new Integer(23);//創(chuàng)建了新的對(duì)象
ps.我感覺(jué)這個(gè)的設(shè)計(jì)思路和數(shù)據(jù)庫(kù)連接池是差不多的,可以對(duì)照著去理解。
參考資料
《深入理解Java虛擬機(jī)》
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Mybatis不啟動(dòng)項(xiàng)目直接測(cè)試Mapper的實(shí)現(xiàn)方法
在項(xiàng)目開(kāi)發(fā)中,測(cè)試單個(gè)Mybatis Mapper方法通常需要啟動(dòng)整個(gè)SpringBoot項(xiàng)目,消耗大量時(shí)間,本文介紹通過(guò)Main方法和Mybatis配置類,快速測(cè)試Mapper功能,無(wú)需啟動(dòng)整個(gè)項(xiàng)目,這方法使用AnnotationConfigApplicationContext容器2024-09-09
一次Jvm old過(guò)高的排查過(guò)程實(shí)戰(zhàn)記錄
這篇文章主要給大家介紹了一次Jvm old過(guò)高的排查過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2018-11-11
Java 代碼實(shí)例解析設(shè)計(jì)模式之監(jiān)聽(tīng)者模式
所謂監(jiān)聽(tīng)者模式,我理解的是構(gòu)建一個(gè)容器存放所有被監(jiān)聽(tīng)的線程或?qū)ο?,監(jiān)聽(tīng)每個(gè)線程或?qū)ο蟀l(fā)生的變化,若某個(gè)線程或?qū)ο笥|發(fā)指定規(guī)則,那么則對(duì)所有被監(jiān)聽(tīng)的線程或?qū)ο蟾鶕?jù)業(yè)務(wù)需要做處理2021-10-10
SpringBoot接入ftp/ftps并上傳文件和配置的代碼指南
接入ftp服務(wù)器,在springboot上實(shí)現(xiàn)起來(lái)也不算復(fù)雜,本文主要講下如何在springboot下接入ftp服務(wù)上傳文件,并對(duì)出現(xiàn)的問(wèn)題做一些記錄,ftp服務(wù)的參數(shù)配置等,需要的朋友可以參考下2024-12-12
Java語(yǔ)言實(shí)現(xiàn)快速冪取模算法詳解
這篇文章主要介紹了Java語(yǔ)言實(shí)現(xiàn)快速冪取模算法詳解,具有一定參考價(jià)值,需要的朋友可以了解下。2017-11-11
Java中如何將?int[]?數(shù)組轉(zhuǎn)換為?ArrayList(list)
這篇文章主要介紹了Java中將?int[]?數(shù)組?轉(zhuǎn)換為?List(ArrayList),本文通過(guò)示例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
Mybatis-Plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例
面對(duì)復(fù)雜多變的業(yè)務(wù)需求,動(dòng)態(tài)表名的處理變得愈發(fā)重要,本文主要介紹了Mybatis-Plus動(dòng)態(tài)表名的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-07-07

