欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

圖解JVM內(nèi)存模型

 更新時(shí)間:2020年10月14日 15:15:30   作者:H.U.C-王子  
這篇文章主要介紹了JVM內(nèi)存模型的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java虛擬機(jī),感興趣的朋友可以了解詳細(xì)

前言

上篇文章我們一起了解了jvm虛擬機(jī)類(lèi)的加載機(jī)制,而且是以一種純大白話(huà)進(jìn)行的一場(chǎng)閑聊,相信小伙伴們應(yīng)該印象深刻,感興趣的小伙伴可以重溫一下上一篇文章大白話(huà)談JVM的類(lèi)加載機(jī)制。

當(dāng)jvm加載了類(lèi)后,會(huì)把需要使用的對(duì)象放入到內(nèi)存當(dāng)中,那么jvm的內(nèi)存模型是什么樣的呢?

今天我們就來(lái)探索一下jvm的內(nèi)存模型。由于有小伙伴反映想加些圖更容易理解,王子接下來(lái)的文章打算用更多的圖例來(lái)講解。

方法區(qū)

很多小伙伴之前也了解過(guò)jvm的內(nèi)存模型,知道有方法區(qū)這個(gè)東西,但可能了解的不是很詳細(xì)。

其實(shí)方法區(qū)是在JDK1.8以前的版本里存在的一塊內(nèi)存區(qū)域,主要就是存放從class文件里加載進(jìn)來(lái)的類(lèi)的,而且常量池也是在這塊區(qū)域內(nèi)的。

但是在JDK1.8之后,這塊區(qū)域搖身一變,換了名字,叫做“Metaspace”,翻譯過(guò)來(lái)就是“元數(shù)據(jù)空間”的意思。當(dāng)然它只是改了個(gè)名,實(shí)現(xiàn)的功能是沒(méi)變的。

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

假設(shè)我們的代碼是這樣的:

public class Main {
 public static void main(String[] args) {
  SysUser sysUser = new SysUser();
  sysUser.setAvatar("1");
 }
}

這個(gè)是我們的java代碼,是面向我們開(kāi)發(fā)者的,然后會(huì)編譯成class字節(jié)碼文件,在class字節(jié)碼文件中存放的是一條條的字節(jié)碼命令,他對(duì)應(yīng)了一條條的機(jī)器指令,計(jì)算機(jī)只有讀到機(jī)器指令才知道它要干什么。

所以當(dāng)JVM加載類(lèi)信息后,實(shí)際上就是使用字節(jié)碼執(zhí)行引擎去執(zhí)行我們的代碼編譯出來(lái)的一條條字節(jié)碼指令,如下圖。

那么在執(zhí)行字節(jié)碼指令的時(shí)候,jvm是怎么知道該執(zhí)行哪條指令了呢?這時(shí)候程序計(jì)數(shù)器就出現(xiàn)了。

它就是用來(lái)記錄當(dāng)前執(zhí)行的字節(jié)碼指令位置的。

另外,小伙伴們都知道,JVM是支持多線(xiàn)程的,所以如果我們開(kāi)啟了多線(xiàn)程,就會(huì)有多個(gè)線(xiàn)程在執(zhí)行不同的字節(jié)碼指令,為了他們之間的字節(jié)碼指令不會(huì)混在一起,所以每個(gè)線(xiàn)程都會(huì)有自己的程序計(jì)數(shù)器,用來(lái)記錄每個(gè)線(xiàn)程自己的指令現(xiàn)在執(zhí)行到哪一條了,如下圖:

 

JAVA虛擬機(jī)棧

我們現(xiàn)在知道,jvm執(zhí)行class中指令時(shí)是通過(guò)程序計(jì)數(shù)器來(lái)鎖定執(zhí)行的指令位置的,但是在我們執(zhí)行的方法里,會(huì)有很多的局部變量等數(shù)據(jù),虛擬機(jī)棧就是用來(lái)保存方法的局部變量的,而且每個(gè)線(xiàn)程都會(huì)有自己的虛擬機(jī)棧,比如我們之前的代碼:

public class Main {
 public static void main(String[] args) {
  SysUser sysUser = new SysUser();
  sysUser.setAvatar("1");
 }
}

這個(gè)代碼會(huì)啟動(dòng)一個(gè)main線(xiàn)程,并把局部變量sysUser保存到棧中。

如果線(xiàn)程執(zhí)行了一個(gè)方法,就會(huì)對(duì)這個(gè)方法調(diào)用創(chuàng)建一個(gè)棧幀,然后就是所謂的壓棧操作(先進(jìn)后出),如下:

然后我們代碼繼續(xù)執(zhí)行,調(diào)用了setAvatar方法,那么就會(huì)繼續(xù)創(chuàng)建棧幀,如下:

當(dāng)setAcatar方法執(zhí)行完畢,就會(huì)對(duì)方法的棧幀執(zhí)行出棧操作。

以上就是JAVA虛擬機(jī)棧這一部分的作用,簡(jiǎn)單概括就是:調(diào)用方法就創(chuàng)建棧幀,壓棧,方法執(zhí)行完就執(zhí)行出棧操作。

JAVA堆內(nèi)存

說(shuō)完了java虛擬機(jī)棧,那我們?cè)賮?lái)說(shuō)一個(gè)很重要的內(nèi)存區(qū)域java堆內(nèi)存,它是用來(lái)存放我們代碼中創(chuàng)建的各種對(duì)象的。

還是以剛才的代碼為例,當(dāng)我們執(zhí)行new SysUser()的時(shí)候,就創(chuàng)建了一個(gè)SysUser實(shí)例對(duì)象,而這個(gè)對(duì)象本身又會(huì)有很多的屬性和方法,這樣的實(shí)例化對(duì)象的數(shù)據(jù)就是存放在堆內(nèi)存中的。

而這個(gè)時(shí)候我們?cè)跅V写鎯?chǔ)的局部變量實(shí)際上存的就是這個(gè)對(duì)象的內(nèi)存地址,也可以理解為一個(gè)引用地址。如下圖:

到這里JVM的內(nèi)存區(qū)域已經(jīng)和小伙伴們介紹完了,給大家來(lái)一張整體的內(nèi)存區(qū)域圖,以便理解:

其他內(nèi)存區(qū)域

除了前文我們介紹的內(nèi)存區(qū)域,jdk的api中(io、nio、socket)相關(guān),其實(shí)它們的內(nèi)部已經(jīng)不是java代碼了,而是調(diào)用了native方法調(diào)用了本地操作系統(tǒng)的一些方法,可能是c語(yǔ)言編寫(xiě)的或者是一些底層類(lèi)庫(kù)。

在調(diào)用native方法的時(shí)候,線(xiàn)程就會(huì)對(duì)應(yīng)本地方法棧,這個(gè)是于java虛擬機(jī)棧類(lèi)似的東東,放的就是native方法的各種局部變量表。

除此之外還有一個(gè)區(qū)域,是不屬于JVM的,通過(guò)NIO的allocateDirect的api,可以在堆外分配內(nèi)存空間,從而直接操作堆外的內(nèi)存空間數(shù)據(jù)。

有些場(chǎng)景下,堆外內(nèi)存空間會(huì)提升性能,這個(gè)問(wèn)題我們之后再逐步探索,今天就不說(shuō)這個(gè)了。

總結(jié)

本文到這里就結(jié)束啦,王子采納了一些小伙伴的意見(jiàn),畫(huà)了很多圖有助于小伙伴們更好的理解,希望能夠幫到大家。

那我們下篇文章見(jiàn)。

以上就是圖解JVM內(nèi)存模型的詳細(xì)內(nèi)容,更多關(guān)于JVM內(nèi)存模型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Druid連接池未關(guān)閉導(dǎo)致內(nèi)存泄漏問(wèn)題

    Druid連接池未關(guān)閉導(dǎo)致內(nèi)存泄漏問(wèn)題

    這篇文章主要介紹了Druid連接池未關(guān)閉導(dǎo)致內(nèi)存泄漏問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • 解決SpringBoot文件上傳臨時(shí)目錄找不到的問(wèn)題

    解決SpringBoot文件上傳臨時(shí)目錄找不到的問(wèn)題

    這篇文章主要介紹了解決SpringBoot文件上傳臨時(shí)目錄找不到的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java?超詳細(xì)帶你掌握矩陣的運(yùn)算

    Java?超詳細(xì)帶你掌握矩陣的運(yùn)算

    在學(xué)習(xí)機(jī)器學(xué)習(xí)算法時(shí),發(fā)現(xiàn)運(yùn)用java?來(lái)實(shí)現(xiàn)有些算法代碼時(shí),會(huì)有很大困難,其中有一點(diǎn)就是?java?本身并沒(méi)有矩陣運(yùn)算的?api,所以進(jìn)行要實(shí)現(xiàn)矩陣運(yùn)算就尤其復(fù)雜,讓我們一起了解矩陣的運(yùn)算
    2022-03-03
  • 解決springboot mapper注入報(bào)紅問(wèn)題

    解決springboot mapper注入報(bào)紅問(wèn)題

    這篇文章主要介紹了解決springboot mapper注入報(bào)紅問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 如何解決java:找不到符號(hào)符號(hào):類(lèi)__(使用了lombok的注解)

    如何解決java:找不到符號(hào)符號(hào):類(lèi)__(使用了lombok的注解)

    在使用IntelliJ IDEA開(kāi)發(fā)Java項(xiàng)目時(shí),可能遇到通過(guò)@lombok注解自動(dòng)生成get和set方法不生效的問(wèn)題,解決這一問(wèn)題需要幾個(gè)步驟,首先,確認(rèn)Lombok插件已在IDEA中安裝并啟用,其次,確保項(xiàng)目中已添加Lombok的依賴(lài),對(duì)于Maven和Gradle項(xiàng)目
    2024-10-10
  • Spring Boot中如何使用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

    Spring Boot中如何使用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器

    這篇文章主要介紹了Spring Boot中使用Convert接口實(shí)現(xiàn)類(lèi)型轉(zhuǎn)換器的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Lombok注解之@SuperBuilder--解決無(wú)法builder父類(lèi)屬性問(wèn)題

    Lombok注解之@SuperBuilder--解決無(wú)法builder父類(lèi)屬性問(wèn)題

    這篇文章主要介紹了Lombok注解之@SuperBuilder--解決無(wú)法builder父類(lèi)屬性問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • 詳解如何判斷Java線(xiàn)程池任務(wù)已執(zhí)行完

    詳解如何判斷Java線(xiàn)程池任務(wù)已執(zhí)行完

    線(xiàn)程池的使用并不復(fù)雜,麻煩的是如何判斷線(xiàn)程池中的任務(wù)已經(jīng)全部執(zhí)行完了,所以接下來(lái),我們就來(lái)看看如何判斷線(xiàn)程中的任務(wù)是否已經(jīng)全部執(zhí)行完吧
    2023-08-08
  • SpringBoot通過(guò)Nginx代理獲取真實(shí)IP

    SpringBoot通過(guò)Nginx代理獲取真實(shí)IP

    springboot作為后臺(tái)代碼,獲取到的登錄IP是前臺(tái)的代理服務(wù)器地址,并不是用戶(hù)的真實(shí)IP地址,本文主要介紹了SpringBoot通過(guò)Nginx代理獲取真實(shí)IP,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Java super關(guān)鍵字用法實(shí)戰(zhàn)案例分析

    Java super關(guān)鍵字用法實(shí)戰(zhàn)案例分析

    這篇文章主要介紹了Java super關(guān)鍵字用法,結(jié)合具體案例形式分析了java super關(guān)鍵字調(diào)用父類(lèi)構(gòu)造方法、屬性及方法等相關(guān)操作技巧與注意事項(xiàng),需要的朋友可以參考下
    2019-09-09

最新評(píng)論