<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一個Java類在運行時候,變量是怎么在JVM中分布的呢?

          共 2656字,需瀏覽 6分鐘

           ·

          2021-07-02 13:09

          JVM學習第三篇思考:一個Java類在Jvm內(nèi)存中是怎么存在的

          又名:Java虛擬機的內(nèi)存模型(JMM)是什么樣的.

          通過前面兩篇文章的學習,我們知道了一個Java類的生命周期及類加載器。我們可以得到如下兩幅圖:

          類生命周期:

          編輯

          父類委托機制:

          編輯

          思考:

          編輯

          我們編寫的類中的變量、方法、對象這些都需要內(nèi)存存放的。那么在運行時候這些數(shù)據(jù)在Java虛擬機內(nèi)存中是怎么存放的呢?

          本文目標:

          凱哥(凱哥Java:kaigejava)希望通過本文學習,大家對Java虛擬機運行時數(shù)據(jù)區(qū)域有更深的了解

          我們寫的代碼在JVM中是怎么存在的?

          1:我們現(xiàn)在看看總體Java運行時數(shù)據(jù)模型:

          編輯

          2:我們來看看下面這段代碼,執(zhí)行的時候,在JVM中數(shù)據(jù)存放:

          編輯

          上面代碼很簡單,那么對應的變量、對象等在內(nèi)存中都是怎么分配的呢?

          2.1:方法區(qū)

          注:在JDK1.8之后,方法區(qū)被元空間替換了。

          方法區(qū):用來存放的是類的信息、常量、靜態(tài)變量等。該區(qū)域也是各個線程共享的內(nèi)存區(qū)域。

          根據(jù)Java虛擬機規(guī)范中的規(guī)定,當方法去無法滿足內(nèi)存分配的時候,會拋出:OutOfMemoryError異常的。

          根據(jù)上面的 定義,我們可以知道比如我們JvmDemo.class信息、static string str=“jvmDemo”是在方法區(qū)存放的。

          對應咱們代碼,方法區(qū)存放的如下圖:

          編輯

          2.2:堆區(qū)

          堆區(qū)是JVM所管理的內(nèi)存中的最大的一塊區(qū)域。該區(qū)域是所有線程共享的一塊內(nèi)存區(qū)域。該區(qū)域空間在虛擬機啟動的時候就被創(chuàng)建了(-Xms的設置。后面凱哥(凱哥Java:kaigejava)也會詳細講解的)。

          此區(qū)域的目的是存放對象實例的。幾乎所有的對象實例都是在這里分配的。Java虛擬機規(guī)范中是這么描述的:所有的對象的實例以及數(shù)組都要在堆上分配。

          堆區(qū)是垃圾收集器管理的主要區(qū)域(后面凱哥(凱哥Java:kaigejava)也會詳細講解的).

          堆區(qū)空間,在物理上可以不是連續(xù)的內(nèi)存空間,只要在邏輯上是連續(xù)的即可。如果堆沒有內(nèi)存完成實例分配,并且堆也無法在擴展的時候,將會拋出異常:OutOfMemoryError。這個大家很熟悉吧。

          根據(jù)上面定義的,我們可以知道,上面代碼中Son son = new Son(); 這行代碼創(chuàng)建的實例對象是存放在堆區(qū)的。

          編輯

          2.3:程序計數(shù)器

          程序計數(shù)器的作用可以看做是當前線程所執(zhí)行的字節(jié)碼的行號指示器。字節(jié)碼解釋器在工作的時候,時候通過改變計數(shù)器的值來選擇接下來要執(zhí)行的字節(jié)碼指令的。

          同時我們都知道,當多線程的時候,Java虛擬機是通過線程輪流切換分配處理器執(zhí)行時間的方式來實現(xiàn)的。在任何一個確定的時刻一個處理器只會執(zhí)行一條線程中的指令。因此,為了解決多個線程在切換后,能夠迅速恢復到切換前執(zhí)行的位置,每個線程都需要有個獨立的程序計數(shù)器,各個線程直接的計數(shù)器互不影響,獨立存儲的。一般稱這類內(nèi)存區(qū)域為:"線程私有"的內(nèi)存。當線程正在執(zhí)行的一個方法是Native的,這種情況下,計數(shù)器的值就是undefined了。這個區(qū)域也是Java虛擬機內(nèi)存區(qū)域中唯一一個沒有OOM的區(qū)域。

          根據(jù)上面描述,我們可以知道,我們自己編寫的*.java文件要想被執(zhí)行,需要被編譯成*.class的字節(jié)碼文件。字節(jié)碼文件對應各種字節(jié)碼指令。比如我們上面JvmDemo的字節(jié)碼文件:

          編輯

          從上面截圖,我們可以看到,行號是0,3,4,7,8這樣的。程序計數(shù)器就是記錄這些行號的

          我們也可以使用idea的插件,來查看我們JvmDemo的相關信息:

          編輯

          2.4:虛擬機棧

          Java虛擬機棧,也是線程私有的。其生命周期與線程相同,當一個線程運行結束后,對應的虛擬機棧也結束。

          虛擬機棧是Java方法執(zhí)行的內(nèi)存模型:即每個方法被執(zhí)行的時候,都會被同時創(chuàng)建一個棧幀(Stack Frame),這個棧幀是用來存放方法局部變量表、操作棧、動態(tài)鏈接、方法出口等信息。每一個方法被調(diào)用直到其執(zhí)行完成的過程,就對應著一個棧幀在虛擬機棧中入棧和出棧的過程。

          比如:我們上面代碼執(zhí)行的時候,執(zhí)行main方法的時候,主線程就會把main方法壓入到虛擬機棧中,當執(zhí)行到add方法的時候,add方法就被壓入到棧中了。當執(zhí)行完add方法后,add方法就被從虛擬機棧中彈出,這個時候add對應的棧幀也銷毀。

          虛擬機棧幀如下圖:

          編輯

          局部變量存放:各種基本數(shù)據(jù)類型、對象引用和返回類型

          八大基本數(shù)據(jù)類型:boolean、byte、char、short、init、float、long、double;

          對象引用:reference類型。這里是存放的是對象在對內(nèi)存中的地址值。不等同于對象自身的。根據(jù)不同的虛擬機的實現(xiàn),這個指向可能是指向了對象起始地址的引用指針,也有可能是指向了對象對象的句柄或其他對象與其他對象的位置;

          返回類型:returnAddress類型。指向一條字節(jié)碼指令地址。

          擴展:long類型和double類型的數(shù)據(jù)會占用2個局部變量空間。其他6個數(shù)據(jù)類型占用1個。

          局部變量表所消耗的內(nèi)存空間在編譯期間就完成了分配,當進入一個方法的時候,這個方法需要在棧幀中分配多大的局部變量空間是完全確定的。在方法的運行期間,不會改變該區(qū)域空間大小的。

          在咱們上面代碼中,虛擬機棧存放的就是咱們main方法和add方法相關的

          2.5:本地方法棧

          本地方法棧的作用和虛擬機棧的作用相似。不同之處在于:虛擬機棧是為了虛擬機執(zhí)行Java方法服務的。而本地方法棧則是為了虛擬機使用到Native方法服務的。此區(qū)域也是方法私有的。比如我們調(diào)用線程的run方法或者CAS的時候,調(diào)用的都是native方法。

          總結:

          通過本文學習,我們在自己腦海中應該有如下圖的概念:

          編輯

          其中方法區(qū)、堆區(qū)是所有線程共享的;虛擬機棧、程序計數(shù)器、本地方法棧這三個是線程私有的,其生命周期同線程一致。

          方法區(qū):存放類型、常量、靜態(tài)變量等

          堆區(qū):用來存放對象實例、數(shù)組

          虛擬機棧:局部變量表、動態(tài)鏈接、操作棧等

          本地方法棧:用來存放當線程調(diào)用native方法的時候使用的

          程序計數(shù)器:用來記錄當前線程執(zhí)行的字節(jié)碼行號的。

          好了,本文凱哥(凱哥Java:kaigejava)就和大家嘮嘮在運行時候Java虛擬機的數(shù)據(jù)區(qū)域。在下篇文章中,咱們在詳細嘮嘮堆區(qū)。


          瀏覽 76
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲色婷婷综合久久久中文 | 人妻摸一摸日日爽一爽,免费视频 | 亚洲AV成人无码久久精品毛片 | 国产人妖视频 | 九色|PORNY|自拍视频 |