JVM-內(nèi)存模型

前言

近幾個(gè)月學(xué)習(xí)了儒猿技術(shù)窩的專欄《從 0 開(kāi)始帶你成為JVM實(shí)戰(zhàn)高手》后,基于課程講解的知識(shí),做了提煉、歸納、擴(kuò)展,整理出當(dāng)前文章。

感謝專欄傳授的知識(shí)!專欄中從零開(kāi)始,一步一圖的方式,加上大量真實(shí)線上案例講解,讓我收獲很多。

一、內(nèi)存區(qū)域整體介紹

1 JDK1.7至JDK1.8的內(nèi)存區(qū)域演變

image.png

主要改變

元數(shù)據(jù)空間取代了方法區(qū),方法區(qū)是在虛擬機(jī)中,而元數(shù)據(jù)空間在本地內(nèi)存中。

2 JDK1.8內(nèi)存區(qū)域的詳細(xì)劃分

image.png

3.代碼執(zhí)行時(shí)的完整的流程

示例代碼

image.png

執(zhí)行流程

image.png

二、內(nèi)存區(qū)域劃分

1 方法區(qū)

JDK1.8以前叫方法區(qū),1.8以后叫"Metaspace"元數(shù)據(jù)空間.

(1)是否線程共享

線程共享。

(2)功能

存放已被虛擬機(jī)加載的類信息、常量、靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)。

(3)JDK1.8的改動(dòng)

JDK1.8后,元空間替換了永久代,

主要改動(dòng)

  1. 元空間使用的是本地內(nèi)存,即不在JVM內(nèi)存區(qū)域中。

  2. 字符串常量由永久代轉(zhuǎn)移到堆中

  3. 和永久代相關(guān)的JVM參數(shù)已移除

可參考:

Metaspace 之一:Metaspace整體介紹(永久代被替換原因、元空間特點(diǎn)、元空間內(nèi)存查看分析方法)【非常好的文章】

2 程序計(jì)數(shù)器

(1)線程是否共享

線程獨(dú)享

(2)功能

JAVA代碼會(huì)被翻譯成字節(jié)碼,對(duì)應(yīng)各種字節(jié)碼指令。

如果線程正在執(zhí)行一個(gè)JAVA方法,計(jì)數(shù)器記錄當(dāng)前線程執(zhí)行到了哪一條字節(jié)碼指令;

如果是正在執(zhí)行的是Native方法,計(jì)數(shù)器的值為Undefined。

此內(nèi)存區(qū)域是唯一一個(gè)在JAVA虛擬機(jī)規(guī)范中沒(méi)有規(guī)定任何OutOfMemoryError情況的區(qū)域。

3 JAVA虛擬機(jī)棧

3.1 整體介紹

(1) 是否線程共享

線程獨(dú)享

(2) 功能

每當(dāng)線程啟動(dòng)的時(shí)候,就會(huì)分配一個(gè)Java虛擬機(jī)棧。

(3) JAVA虛擬機(jī)棧作用

執(zhí)行方法時(shí),會(huì)給方法創(chuàng)建棧幀然后入棧,在棧幀里存放這個(gè)方法對(duì)應(yīng)的局部變量之類的數(shù)據(jù)。

方法執(zhí)行完后,方法對(duì)應(yīng)的棧幀從虛擬機(jī)棧中出棧。(后面再深入學(xué)習(xí)入棧、出棧)

(4) 可能發(fā)生的錯(cuò)誤

StackOverflowError: 線程請(qǐng)求的棧深度大于虛擬機(jī)所允許的深度,JDK1.8默認(rèn)棧最大大小是1M。

OutOfMemoryError: 如果虛擬機(jī)棧可以動(dòng)態(tài)擴(kuò)展,而擴(kuò)展時(shí)無(wú)法申請(qǐng)到足夠的內(nèi)存。(后面再深入學(xué)這兩個(gè)Error)

3.1 棧幀

(1) 功能

線程執(zhí)行了一個(gè)方法,會(huì)對(duì)這個(gè)方法調(diào)用創(chuàng)建對(duì)應(yīng)的一個(gè)棧幀。

棧幀里包含這個(gè)方法的局部變量表、操作樹(shù)棧、動(dòng)態(tài)鏈接、方法出口。

局部變量表:存放了編譯期可知的各種基本類型(int、float等)、對(duì)象引用(指向堆內(nèi)存的地址)、returnAddress類型(指向了一條字節(jié)碼指令的地址)。

示例代碼中main線程執(zhí)行時(shí)的虛擬機(jī)棧內(nèi)存情況:

image.png

4 JAVA堆內(nèi)存

(1) 是否線程共享

線程共享。

(2) 功能

主要存放對(duì)象實(shí)例和數(shù)組。

可以物理上不連續(xù),但邏輯上要連續(xù)。

局部變量表的局部變量指向堆內(nèi)存的對(duì)象:

image.png

(3) 創(chuàng)建的對(duì)象在堆內(nèi)存中占用多少內(nèi)存?

一個(gè)對(duì)象對(duì)堆內(nèi)存空間的占用,大致分為兩塊:

(1)對(duì)象自己本身的一些信息

比如對(duì)象頭,在64位的Linux操作系統(tǒng)上,會(huì)占用16個(gè)字節(jié)。

(2)對(duì)象的實(shí)例變量作為數(shù)據(jù)占用的空間

各個(gè)實(shí)例變量占用的內(nèi)存,例如int類型占用4個(gè)字節(jié),long類型占用8個(gè)字節(jié)。還有數(shù)組、Map之類的會(huì)占用更多內(nèi)存。

5 本地方法棧

5.1 整體介紹

(1) 是否線程共享

線程獨(dú)享

(2) 功能

本地方法棧是為虛擬機(jī)使用到的Native方法服務(wù)。Java虛擬機(jī)棧是為執(zhí)行Java方法(也就是字節(jié)碼)服務(wù)。

(3) 可能發(fā)生的錯(cuò)誤

和虛擬機(jī)棧一樣,也會(huì)有StackOverflowError和OutOfMemoryError錯(cuò)誤。

6 直接內(nèi)存

(1) 是否線程共享

線程共享

(2) 功能

為虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的部分。

在JDK1.4中新加入NIO(New Input/Output)類,引入了一種基于通道(Channel)和緩存(Buffer)的I/O方式,它可以使用Native函數(shù)庫(kù)直接分配堆外內(nèi)存,然后通過(guò)一個(gè)存儲(chǔ)在Java堆中的DirectByteBuffer對(duì)象作為這塊內(nèi)存的引用進(jìn)行操作。
Netty框架就是使用了直接內(nèi)存。

(3) 作用

可以避免在Java堆和Native堆中來(lái)回的耗時(shí)操作。

(4) 可能發(fā)生的錯(cuò)誤

OutOfMemoryError: 會(huì)受到本機(jī)內(nèi)存限制,如果內(nèi)存區(qū)域總和大于物理內(nèi)存限制從而導(dǎo)致動(dòng)態(tài)擴(kuò)展時(shí)出現(xiàn)該異常。

參考:

Java虛擬機(jī)(JVM)你只要看這一篇就夠了! https://blog.csdn.net/qq_41701956/article/details/81664921

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1 CPU和內(nèi)存的交互 了解jvm內(nèi)存模型前,了解下cpu和計(jì)算機(jī)內(nèi)存的交互情況?!疽?yàn)镴ava虛擬機(jī)內(nèi)存模型定義...
    Zal哥哥閱讀 280評(píng)論 0 2
  • 1 CPU和內(nèi)存的交互 了解jvm內(nèi)存模型前,了解下cpu和計(jì)算機(jī)內(nèi)存的交互情況?!疽?yàn)镴ava虛擬機(jī)內(nèi)存模型定義...
    Garwer閱讀 374,448評(píng)論 54 551
  • 如圖: 運(yùn)行時(shí)數(shù)據(jù)區(qū)主要有 5個(gè)核心區(qū);又根據(jù)是否線程私有分為兩部分 線程私有:方法區(qū)(含有運(yùn)行時(shí)常量池)、堆 線...
    小碼毅閱讀 208評(píng)論 0 0
  • 1,程序計(jì)數(shù)器 1.1 用于存儲(chǔ)每個(gè)線程下一步將執(zhí)行的jvm指令 1.2 如該方法是Native的,則不存儲(chǔ)任何信...
    lqq2019閱讀 339評(píng)論 0 0
  • 2、Java內(nèi)存區(qū)域與Java內(nèi)存模型 1)Java內(nèi)存區(qū)域 Java虛擬機(jī)在運(yùn)行程序時(shí)會(huì)把其自動(dòng)管理的內(nèi)存劃分為...
    脆皮雞大蝦閱讀 948評(píng)論 0 2

友情鏈接更多精彩內(nèi)容