最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JVM內(nèi)存區(qū)域劃分相關(guān)原理詳解

 更新時(shí)間:2020年10月27日 09:22:19   投稿:yaominghui  
這篇文章主要介紹了JVM內(nèi)存區(qū)域劃分相關(guān)原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

  學(xué)過(guò)C語(yǔ)言的朋友都知道C編譯器在劃分內(nèi)存區(qū)域的時(shí)候經(jīng)常將管理的區(qū)域劃分為數(shù)據(jù)段和代碼段,數(shù)據(jù)段包括堆、棧以及靜態(tài)數(shù)據(jù)區(qū)。那么在Java語(yǔ)言當(dāng)中,內(nèi)存又是如何劃分的呢?

  由于Java程序是交由JVM執(zhí)行的,所以我們?cè)谡凧ava內(nèi)存區(qū)域劃分的時(shí)候事實(shí)上是指JVM內(nèi)存區(qū)域劃分。在討論JVM內(nèi)存區(qū)域劃分之前,先來(lái)看一下Java程序具體執(zhí)行的過(guò)程:

  

  如上圖所示,首先Java源代碼文件(.java后綴)會(huì)被Java編譯器編譯為字節(jié)碼文件(.class后綴),然后由JVM中的類(lèi)加載器加載各個(gè)類(lèi)的字節(jié)碼文件,加載完畢之后,交由JVM執(zhí)行引擎執(zhí)行。在整個(gè)程序執(zhí)行過(guò)程中,JVM會(huì)用一段空間來(lái)存儲(chǔ)程序執(zhí)行期間需要用到的數(shù)據(jù)和相關(guān)信息,這段空間一般被稱作為Runtime Data Area(運(yùn)行時(shí)數(shù)據(jù)區(qū)),也就是我們常說(shuō)的JVM內(nèi)存。因此,在Java中我們常常說(shuō)到的內(nèi)存管理就是針對(duì)這段空間進(jìn)行管理(如何分配和回收內(nèi)存空間)。

  在知道了JVM內(nèi)存是什么東西之后,下面我們就來(lái)討論一下這段空間具體是如何劃分區(qū)域的,是不是也像C語(yǔ)言中一樣也存在棧和堆呢?

一.運(yùn)行時(shí)數(shù)據(jù)區(qū)包括哪幾部分?

  根據(jù)《Java虛擬機(jī)規(guī)范》的規(guī)定,運(yùn)行時(shí)數(shù)據(jù)區(qū)通常包括這幾個(gè)部分:程序計(jì)數(shù)器(Program Counter Register)、Java棧(VM Stack)、本地方法棧(Native Method Stack)、方法區(qū)(Method Area)、堆(Heap)。

  如上圖所示,JVM中的運(yùn)行時(shí)數(shù)據(jù)區(qū)應(yīng)該包括這些部分。在JVM規(guī)范中雖然規(guī)定了程序在執(zhí)行期間運(yùn)行時(shí)數(shù)據(jù)區(qū)應(yīng)該包括這幾部分,但是至于具體如何實(shí)現(xiàn)并沒(méi)有做出規(guī)定,不同的虛擬機(jī)廠商可以有不同的實(shí)現(xiàn)方式。

二.運(yùn)行時(shí)數(shù)據(jù)區(qū)的每部分到底存儲(chǔ)了哪些數(shù)據(jù)?

  下面我們來(lái)了解一下運(yùn)行時(shí)數(shù)據(jù)區(qū)的每部分具體用來(lái)存儲(chǔ)程序執(zhí)行過(guò)程中的哪些數(shù)據(jù)。

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

  程序計(jì)數(shù)器(Program Counter Register),也有稱作為PC寄存器。想必學(xué)過(guò)匯編語(yǔ)言的朋友對(duì)程序計(jì)數(shù)器這個(gè)概念并不陌生,在匯編語(yǔ)言中,程序計(jì)數(shù)器是指CPU中的寄存器,它保存的是程序當(dāng)前執(zhí)行的指令的地址(也可以說(shuō)保存下一條指令的所在存儲(chǔ)單元的地址),當(dāng)CPU需要執(zhí)行指令時(shí),需要從程序計(jì)數(shù)器中得到當(dāng)前需要執(zhí)行的指令所在存儲(chǔ)單元的地址,然后根據(jù)得到的地址獲取到指令,在得到指令之后,程序計(jì)數(shù)器便自動(dòng)加1或者根據(jù)轉(zhuǎn)移指針得到下一條指令的地址,如此循環(huán),直至執(zhí)行完所有的指令。

  雖然JVM中的程序計(jì)數(shù)器并不像匯編語(yǔ)言中的程序計(jì)數(shù)器一樣是物理概念上的CPU寄存器,但是JVM中的程序計(jì)數(shù)器的功能跟匯編語(yǔ)言中的程序計(jì)數(shù)器的功能在邏輯上是等同的,也就是說(shuō)是用來(lái)指示 執(zhí)行哪條指令的。

  由于在JVM中,多線程是通過(guò)線程輪流切換來(lái)獲得CPU執(zhí)行時(shí)間的,因此,在任一具體時(shí)刻,一個(gè)CPU的內(nèi)核只會(huì)執(zhí)行一條線程中的指令,因此,為了能夠使得每個(gè)線程都在線程切換后能夠恢復(fù)在切換之前的程序執(zhí)行位置,每個(gè)線程都需要有自己獨(dú)立的程序計(jì)數(shù)器,并且不能互相被干擾,否則就會(huì)影響到程序的正常執(zhí)行次序。因此,可以這么說(shuō),程序計(jì)數(shù)器是每個(gè)線程所私有的。

  在JVM規(guī)范中規(guī)定,如果線程執(zhí)行的是非native方法,則程序計(jì)數(shù)器中保存的是當(dāng)前需要執(zhí)行的指令的地址;如果線程執(zhí)行的是native方法,則程序計(jì)數(shù)器中的值是undefined。

  由于程序計(jì)數(shù)器中存儲(chǔ)的數(shù)據(jù)所占空間的大小不會(huì)隨程序的執(zhí)行而發(fā)生改變,因此,對(duì)于程序計(jì)數(shù)器是不會(huì)發(fā)生內(nèi)存溢出現(xiàn)象(OutOfMemory)的。

2.Java棧

  Java棧也稱作虛擬機(jī)棧(Java Vitual Machine Stack),也就是我們常常所說(shuō)的棧,跟C語(yǔ)言的數(shù)據(jù)段中的棧類(lèi)似。事實(shí)上,Java棧是Java方法執(zhí)行的內(nèi)存模型。為什么這么說(shuō)呢?下面就來(lái)解釋一下其中的原因。

  Java棧中存放的是一個(gè)個(gè)的棧幀,每個(gè)棧幀對(duì)應(yīng)一個(gè)被調(diào)用的方法,在棧幀中包括局部變量表(Local Variables)、操作數(shù)棧(Operand Stack)、指向當(dāng)前方法所屬的類(lèi)的運(yùn)行時(shí)常量池(運(yùn)行時(shí)常量池的概念在方法區(qū)部分會(huì)談到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息。當(dāng)線程執(zhí)行一個(gè)方法時(shí),就會(huì)隨之創(chuàng)建一個(gè)對(duì)應(yīng)的棧幀,并將建立的棧幀壓棧。當(dāng)方法執(zhí)行完畢之后,便會(huì)將棧幀出棧。因此可知,線程當(dāng)前執(zhí)行的方法所對(duì)應(yīng)的棧幀必定位于Java棧的頂部。講到這里,大家就應(yīng)該會(huì)明白為什么 在 使用 遞歸方法的時(shí)候容易導(dǎo)致棧內(nèi)存溢出的現(xiàn)象了以及為什么棧區(qū)的空間不用程序員去管理了(當(dāng)然在Java中,程序員基本不用關(guān)系到內(nèi)存分配和釋放的事情,因?yàn)镴ava有自己的垃圾回收機(jī)制),這部分空間的分配和釋放都是由系統(tǒng)自動(dòng)實(shí)施的。對(duì)于所有的程序設(shè)計(jì)語(yǔ)言來(lái)說(shuō),棧這部分空間對(duì)程序員來(lái)說(shuō)是不透明的。下圖表示了一個(gè)Java棧的模型:

  局部變量表,顧名思義,想必不用解釋大家應(yīng)該明白它的作用了吧。就是用來(lái)存儲(chǔ)方法中的局部變量(包括在方法中聲明的非靜態(tài)變量以及函數(shù)形參)。對(duì)于基本數(shù)據(jù)類(lèi)型的變量,則直接存儲(chǔ)它的值,對(duì)于引用類(lèi)型的變量,則存的是指向?qū)ο蟮囊谩>植孔兞勘淼拇笮≡诰幾g器就可以確定其大小了,因此在程序執(zhí)行期間局部變量表的大小是不會(huì)改變的。

  操作數(shù)棧,想必學(xué)過(guò)數(shù)據(jù)結(jié)構(gòu)中的棧的朋友想必對(duì)表達(dá)式求值問(wèn)題不會(huì)陌生,棧最典型的一個(gè)應(yīng)用就是用來(lái)對(duì)表達(dá)式求值。想想一個(gè)線程執(zhí)行方法的過(guò)程中,實(shí)際上就是不斷執(zhí)行語(yǔ)句的過(guò)程,而歸根到底就是進(jìn)行計(jì)算的過(guò)程。因此可以這么說(shuō),程序中的所有計(jì)算過(guò)程都是在借助于操作數(shù)棧來(lái)完成的。

  指向運(yùn)行時(shí)常量池的引用,因?yàn)樵诜椒▓?zhí)行的過(guò)程中有可能需要用到類(lèi)中的常量,所以必須要有一個(gè)引用指向運(yùn)行時(shí)常量。

  方法返回地址,當(dāng)一個(gè)方法執(zhí)行完畢之后,要返回之前調(diào)用它的地方,因此在棧幀中必須保存一個(gè)方法返回地址。

  由于每個(gè)線程正在執(zhí)行的方法可能不同,因此每個(gè)線程都會(huì)有一個(gè)自己的Java棧,互不干擾。

3.本地方法棧

  本地方法棧與Java棧的作用和原理非常相似。區(qū)別只不過(guò)是Java棧是為執(zhí)行Java方法服務(wù)的,而本地方法棧則是為執(zhí)行本地方法(Native Method)服務(wù)的。在JVM規(guī)范中,并沒(méi)有對(duì)本地方發(fā)展的具體實(shí)現(xiàn)方法以及數(shù)據(jù)結(jié)構(gòu)作強(qiáng)制規(guī)定,虛擬機(jī)可以自由實(shí)現(xiàn)它。在HotSopt虛擬機(jī)中直接就把本地方法棧和Java棧合二為一。

4.堆

  在C語(yǔ)言中,堆這部分空間是唯一一個(gè)程序員可以管理的內(nèi)存區(qū)域。程序員可以通過(guò)malloc函數(shù)和free函數(shù)在堆上申請(qǐng)和釋放空間。那么在Java中是怎么樣的呢?

  Java中的堆是用來(lái)存儲(chǔ)對(duì)象本身的以及數(shù)組(當(dāng)然,數(shù)組引用是存放在Java棧中的)。只不過(guò)和C語(yǔ)言中的不同,在Java中,程序員基本不用去關(guān)心空間釋放的問(wèn)題,Java的垃圾回收機(jī)制會(huì)自動(dòng)進(jìn)行處理。因此這部分空間也是Java垃圾收集器管理的主要區(qū)域。另外,堆是被所有線程共享的,在JVM中只有一個(gè)堆。

5.方法區(qū)

  方法區(qū)在JVM中也是一個(gè)非常重要的區(qū)域,它與堆一樣,是被線程共享的區(qū)域。在方法區(qū)中,存儲(chǔ)了每個(gè)類(lèi)的信息(包括類(lèi)的名稱、方法信息、字段信息)、靜態(tài)變量、常量以及編譯器編譯后的代碼等。

  在Class文件中除了類(lèi)的字段、方法、接口等描述信息外,還有一項(xiàng)信息是常量池,用來(lái)存儲(chǔ)編譯期間生成的字面量和符號(hào)引用。

  在方法區(qū)中有一個(gè)非常重要的部分就是運(yùn)行時(shí)常量池,它是每一個(gè)類(lèi)或接口的常量池的運(yùn)行時(shí)表示形式,在類(lèi)和接口被加載到JVM后,對(duì)應(yīng)的運(yùn)行時(shí)常量池就被創(chuàng)建出來(lái)。當(dāng)然并非Class文件常量池中的內(nèi)容才能進(jìn)入運(yùn)行時(shí)常量池,在運(yùn)行期間也可將新的常量放入運(yùn)行時(shí)常量池中,比如String的intern方法。

  在JVM規(guī)范中,沒(méi)有強(qiáng)制要求方法區(qū)必須實(shí)現(xiàn)垃圾回收。很多人習(xí)慣將方法區(qū)稱為“永久代”,是因?yàn)镠otSpot虛擬機(jī)以永久代來(lái)實(shí)現(xiàn)方法區(qū),從而JVM的垃圾收集器可以像管理堆區(qū)一樣管理這部分區(qū)域,從而不需要專門(mén)為這部分設(shè)計(jì)垃圾回收機(jī)制。不過(guò)自從JDK7之后,Hotspot虛擬機(jī)便將運(yùn)行時(shí)常量池從永久代移除了。

  以上為個(gè)人看法和觀點(diǎn),如有不正之處希望諒解并歡迎指正。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java中如何使用泛型方法比較大小

    java中如何使用泛型方法比較大小

    這篇文章主要介紹了java中如何使用泛型方法比較大小,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • springboot的http.server.requests服務(wù)請(qǐng)求流程源碼

    springboot的http.server.requests服務(wù)請(qǐng)求流程源碼

    這篇文章主要為大家介紹了springboot的http.server.requests服務(wù)請(qǐng)求流程源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Java前后端任意參數(shù)類(lèi)型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal)

    Java前后端任意參數(shù)類(lèi)型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal)

    這篇文章主要介紹了Java前后端任意參數(shù)類(lèi)型轉(zhuǎn)換方式(Date、LocalDateTime、BigDecimal),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • SpringMVC執(zhí)行步驟、Model的使用詳解

    SpringMVC執(zhí)行步驟、Model的使用詳解

    這篇文章主要介紹了SpringMVC執(zhí)行步驟、Model的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • SpringCloud中的Stream服務(wù)間消息傳遞詳解

    SpringCloud中的Stream服務(wù)間消息傳遞詳解

    這篇文章主要介紹了SpringCloud中的Stream服務(wù)間消息傳遞詳解,Stream 就是在消息隊(duì)列的基礎(chǔ)上,對(duì)其進(jìn)行封裝,可以是我們更方便的去使用,Stream應(yīng)用由第三方的中間件組成,應(yīng)用間的通信通過(guò)輸入通道和輸出通道完成,需要的朋友可以參考下
    2024-01-01
  • Java枚舉類(lèi)用法實(shí)例

    Java枚舉類(lèi)用法實(shí)例

    這篇文章主要介紹了Java枚舉類(lèi)用法,實(shí)例分析了java中枚舉類(lèi)的實(shí)現(xiàn)與使用技巧,需要的朋友可以參考下
    2015-05-05
  • 如何使用Jenkins構(gòu)建GIT+Maven項(xiàng)目

    如何使用Jenkins構(gòu)建GIT+Maven項(xiàng)目

    這篇文章主要介紹了如何使用Jenkins構(gòu)建GIT+Maven項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Java中Redis存儲(chǔ)String類(lèi)型會(huì)有亂碼的問(wèn)題及解決方案

    Java中Redis存儲(chǔ)String類(lèi)型會(huì)有亂碼的問(wèn)題及解決方案

    在java中使用Redis存儲(chǔ)String類(lèi)型的數(shù)據(jù)時(shí),會(huì)出現(xiàn)亂碼,我寫(xiě)了一條存儲(chǔ)key為name,值為虎哥的字符串,然后獲取一下這個(gè)key為name的值,打印得到的值,下面通過(guò)實(shí)例代碼介紹Java中Redis存儲(chǔ)String類(lèi)型會(huì)有亂碼的問(wèn)題及解決方案,一起看看吧
    2024-04-04
  • MybatisPlus?BaseMapper?實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)增刪改查源碼

    MybatisPlus?BaseMapper?實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)增刪改查源碼

    MybatisPlus?是一款在?Mybatis?基礎(chǔ)上進(jìn)行的增強(qiáng)?orm?框架,可以實(shí)現(xiàn)不寫(xiě)?sql?就完成數(shù)據(jù)庫(kù)相關(guān)的操作,這篇文章主要介紹了MybatisPlus?BaseMapper?實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)增刪改查源碼解析,需要的朋友可以參考下
    2023-01-01
  • Java IO流 文件傳輸基礎(chǔ)

    Java IO流 文件傳輸基礎(chǔ)

    這篇文章主要介紹了Java IO流 文件傳輸基礎(chǔ)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07

最新評(píng)論

海南省| 台州市| 邵东县| 墨竹工卡县| 新营市| 达拉特旗| 成武县| 泗阳县| 肥乡县| 新化县| 通辽市| 黄石市| 和林格尔县| 太仓市| 潢川县| 西城区| 台东市| 乌拉特中旗| 眉山市| 浮山县| 调兵山市| 舞阳县| 陕西省| 达孜县| 连平县| 峨眉山市| 伊宁县| 麻阳| 扎兰屯市| 合肥市| 庐江县| 宾阳县| 开平市| 盈江县| 南充市| 信阳市| 根河市| 来宾市| 龙州县| 克东县| 封开县|