JVM內(nèi)存模型/內(nèi)存空間:運(yùn)行時(shí)數(shù)據(jù)區(qū)
JVM內(nèi)存模型/內(nèi)存空間
Java虛擬機(jī)JVM運(yùn)行起來(lái),就會(huì)給內(nèi)存劃分空間,這塊空間成為運(yùn)行時(shí)數(shù)據(jù)區(qū)。
運(yùn)行時(shí)數(shù)據(jù)區(qū)主要?jiǎng)澐譃橐韵?nbsp;6個(gè) :

① 程序計(jì)數(shù)器 (Program Counter Register)
- 一塊較小的內(nèi)存空間,可以看作是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器
- 線程私有的內(nèi)存
- 值得注意的是:《Java虛擬機(jī)規(guī)范》中,唯一一個(gè)沒(méi)有規(guī)定任何OutOfMemoryError情況的區(qū)域?。?!
程序計(jì)數(shù)器也可以稱(chēng)為PC寄存器,通俗的講就是指令緩存,它主要用來(lái)緩存當(dāng)前程序執(zhí)行的下一條指令的地址,CPU根據(jù)這個(gè)地址找到將要執(zhí)行的指令。這個(gè)寄存器是JVM內(nèi)部實(shí)現(xiàn)的,不是物理概念上的計(jì)數(shù)器,不過(guò)和JVM的實(shí)現(xiàn)邏輯一樣。
② Java虛擬機(jī)棧 (VM Stack)
- Java方法執(zhí)行的線程內(nèi)存模型
- 每一個(gè)線程運(yùn)行起來(lái)的都會(huì)對(duì)應(yīng)一個(gè)棧(線程棧),棧中的數(shù)據(jù)是該線程獨(dú)有的,不會(huì)產(chǎn)生資源共享的情況,因此線程棧是線程安全的。
- 棧當(dāng)中存放的是棧幀
- 每個(gè)Java方法的執(zhí)行對(duì)應(yīng)著一個(gè)棧幀的進(jìn)棧和出棧的操作
- 當(dāng)線程調(diào)用方法時(shí),就形成一個(gè)棧幀,并將這個(gè)棧幀進(jìn)行壓棧操作,方法執(zhí)行完之后進(jìn)行出棧操作。
- 這個(gè)棧幀中包括:局部變量、操作數(shù)棧、指向當(dāng)前方法對(duì)應(yīng)類(lèi)的常量池引用、方法返回地址等信息
- 為虛擬機(jī)執(zhí)行Java方法(也就是字節(jié)碼)服務(wù)
- 線程私有的內(nèi)存
- 其生命周期與線程相同
- 兩類(lèi)異常:
- 如果線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,將拋出StackOverflowError異常
- 如果JVM棧容量可以動(dòng)態(tài)擴(kuò)展,當(dāng)棧擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存時(shí),會(huì)拋出OutOfMemoryError異常
③ 本地方法棧 (Native Method Stack)
區(qū)別于 “Java虛擬機(jī)?!?nbsp;
- 本地方法棧只為虛擬機(jī)使用到的本地(Native)方法服務(wù),為其運(yùn)行提供內(nèi)存環(huán)境
- 本地方法是指JVM需要調(diào)用非Java語(yǔ)言所實(shí)現(xiàn)的方法,例如C/C++/C#
- JVM棧運(yùn)行的是Java方法
在JVM規(guī)范中,沒(méi)有強(qiáng)化性要求實(shí)現(xiàn)方一定要?jiǎng)澐殖霰镜胤椒#ɡ纾篐otSpot虛擬機(jī)將本地方法棧和棧合二為一)和具體實(shí)現(xiàn)(不同的操作系統(tǒng),對(duì)JVM規(guī)范的具體實(shí)現(xiàn)都不一樣)。
- 同 “Java虛擬機(jī)?!?nbsp;一樣,本地方法棧也有兩類(lèi)異常:
- 棧深度溢出時(shí),將拋出StackOverflowError異常
- 棧擴(kuò)展失敗時(shí),會(huì)拋出OutOfMemoryError異常
④ Java堆 (Java Heap)
- 虛擬機(jī)所管理的內(nèi)存中最大的一塊
- Java堆是被所有線程共享的一塊內(nèi)存區(qū)域
- 唯一的目的:存放對(duì)象示例。
- Java中 “幾乎” 所有的對(duì)象實(shí)例都在這里分配內(nèi)存;
- 但是,由于現(xiàn)在技術(shù)發(fā)展,說(shuō) “Java對(duì)象示例都分配在堆上” 也漸漸變得不是那么絕對(duì)了。
- Java堆是垃圾收集器管理的內(nèi)存區(qū)域,也稱(chēng)“GC堆”。
- 堆內(nèi)存中的對(duì)象沒(méi)有被引用,會(huì)自動(dòng)被Java的垃圾回收機(jī)制回收。
- 當(dāng)在方法中定義了局部變量:
- 如果局部變量是基本數(shù)據(jù)類(lèi)型,直接存放在棧內(nèi)存中;
- 如果局部變量是引用數(shù)據(jù)類(lèi)型,會(huì)將變量值存放在堆內(nèi)存中,棧內(nèi)存中只存放引用地址。
- Java堆可以處于物理上不連續(xù)的內(nèi)存空間,但在邏輯上它應(yīng)該是被視為連續(xù)的。
- 如果在Java堆中沒(méi)有內(nèi)存完成實(shí)例分配,并且Java堆也無(wú)法再擴(kuò)展時(shí),Java虛擬機(jī)將會(huì)拋出OutOfMemoryError異常
⑤ 方法區(qū)(Method Area)
- 和 “Java堆” 一樣,是被所有線程共享的一塊區(qū)域。
- 主要存放每一個(gè)被加載的class的信息
class信息主要包含魔數(shù)(確定是否是一個(gè)class文件),常量池,訪問(wèn)標(biāo)志(當(dāng)前的類(lèi)是普通類(lèi)還是接口,是否是抽象類(lèi),是否被public修飾,是否使用了final修飾等描述信息…),字段表集合信息(使用什么訪問(wèn)修飾符,是實(shí)例變量還是靜態(tài)變量,是否使用了final修飾等描述信息…),方法表集合信息(使用什么訪問(wèn)修飾符,是否靜態(tài)方法,是否使用了 final 修飾,是否使用了synchronized修飾,是否是native方法…)等內(nèi)容。
當(dāng)一個(gè)類(lèi)加載器加載了一個(gè)類(lèi)的時(shí)候,會(huì)根據(jù)這個(gè)class文件創(chuàng)建一個(gè)class對(duì)象,class對(duì)象就包含了上述的信息。后續(xù)要?jiǎng)?chuàng)建這個(gè)類(lèi)的實(shí)例,都根據(jù)這個(gè)class對(duì)象創(chuàng)建出來(lái)的。
在《Java虛擬機(jī)規(guī)范》中,把方法區(qū)描述為堆的一個(gè)邏輯部分,但是它卻有一個(gè)別名叫作 “非堆” ,目的是與Java堆區(qū)分開(kāi)來(lái)。
如果方法區(qū)無(wú)法滿(mǎn)足新的內(nèi)存分配需求時(shí),將拋出OutOfMemoryError異常
⑥ 運(yùn)行時(shí)常量池 (Running Constant Pool)
- 運(yùn)行時(shí)常量池是方法區(qū)的一部分。
- 存放class中最重要的資源,JVM為每一個(gè)class對(duì)象都維護(hù)著一個(gè)常量池。
- 常量池表:用于存放編譯期生成的各種字面量與字符引用。
- 這部分內(nèi)容將在類(lèi)加載后存放到方法區(qū)的運(yùn)行時(shí)常量池中。
- 運(yùn)行時(shí)常量池相對(duì)Class文件常量池的一個(gè)重要特征是具備動(dòng)態(tài)性。
- 當(dāng)常量池?zé)o法再申請(qǐng)到內(nèi)存時(shí),會(huì)拋出OutOfMemoryError異常
【特】 直接內(nèi)存
運(yùn)行時(shí)數(shù)據(jù)區(qū)主要為以上6個(gè)區(qū)域,但是JVM所管理的還有一個(gè)較特殊的區(qū)域:
- 直接內(nèi)存 (Direct Memory)
- 既不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,也不是《Java虛擬機(jī)規(guī)范》中定義的內(nèi)存區(qū)域。
- 但是這部分內(nèi)存區(qū)域也被頻繁地使用,而且也可能導(dǎo)致OutOfMemoryError異常出現(xiàn)
1.在JDK 1.4中新加入了NIO(New Input/Output)類(lèi),引入了一種基于通道(Channel)與緩沖區(qū)(Buffer)的I/O方式,它可以使用Native函數(shù)庫(kù) 直接分配堆外內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在Java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。這樣能在一些場(chǎng)景中顯著提高性能,因?yàn)楸苊饬嗽贘ava堆和Native堆中來(lái)回復(fù)制數(shù)據(jù)。
2.在本機(jī)直接內(nèi)存的分配不會(huì)受到Java堆大小的限制,但是,既然是內(nèi)存,則肯定還是會(huì)受到本機(jī)總內(nèi)存(包括RAM及SWAP區(qū)或者分頁(yè)文件)的大小及處理器尋址空間的限制。服務(wù)器管理員配置虛擬機(jī)參數(shù)時(shí),一般會(huì)根據(jù)實(shí)際內(nèi)存設(shè)置-Xmx等參數(shù)信息,但經(jīng)常會(huì)忽略掉直接內(nèi)存,使得各個(gè)內(nèi)存區(qū)域的總和大于物理內(nèi)存限制(包括物理上的和操作系統(tǒng)級(jí)的限制),從而導(dǎo)致動(dòng)態(tài)擴(kuò)展時(shí)出現(xiàn)OutOfMemoryError異常。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
- JAVA JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)詳解
- 面試時(shí)必問(wèn)的JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)詳解
- Java JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)(Run-Time Data Areas)
- JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)劃分原理詳解
- Java內(nèi)存模型與JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的區(qū)別詳解
- JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)原理解析
- Java內(nèi)存模型JMM與volatile
- Java內(nèi)存模型(JMM)及happens-before原理
- JVM?運(yùn)行時(shí)數(shù)據(jù)區(qū)與JMM?內(nèi)存模型
相關(guān)文章
Springboot Autowried及Resouce使用對(duì)比解析
這篇文章主要介紹了Springboot Autowried及Resouce使用對(duì)比解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-06-06
使用jmx?exporter采集kafka指標(biāo)示例詳解
這篇文章主要為大家介紹了使用jmx?exporter采集kafka指標(biāo)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
SpringMVC參數(shù)傳遞之基本數(shù)據(jù)類(lèi)型和復(fù)雜對(duì)象說(shuō)明
這篇文章主要介紹了SpringMVC參數(shù)傳遞之基本數(shù)據(jù)類(lèi)型和復(fù)雜對(duì)象說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
Java?+?Selenium?+?OpenCV解決自動(dòng)化測(cè)試中的滑塊驗(yàn)證問(wèn)題
OpenCV是一個(gè)基于Apache2.0許可(開(kāi)源)發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)和機(jī)器學(xué)習(xí)軟件庫(kù),可以運(yùn)行在Linux、Windows、Android和Mac?OS操作系統(tǒng)上,這篇文章主要介紹了Java?+?Selenium?+?OpenCV解決自動(dòng)化測(cè)試中的滑塊驗(yàn)證,需要的朋友可以參考下2022-07-07
Schedule定時(shí)任務(wù)在分布式產(chǎn)生的問(wèn)題詳解
這篇文章主要介紹了Schedule定時(shí)任務(wù)在分布式產(chǎn)生的問(wèn)題詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10
Java中try-catch的使用及注意細(xì)節(jié)
現(xiàn)在有很多的語(yǔ)言都支持try-catch,比如常見(jiàn)的就是c++,java等,這篇文章主要給大家介紹了關(guān)于Java中try-catch的使用及注意細(xì)節(jié)的相關(guān)資料,文中通過(guò)圖文以及實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
如何運(yùn)行SpringBoot項(xiàng)目的方法
這篇文章主要介紹了如何運(yùn)行SpringBoot項(xiàng)目的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03

