淺析JVM內(nèi)存模型

  • Java虛擬機(jī)內(nèi)存
    ???Java虛擬機(jī)在執(zhí)行Java程序的時(shí)候會(huì)將它管理的內(nèi)存分為若干個(gè)不同的數(shù)據(jù)區(qū)域。不同的區(qū)域用途也各不相同,具體內(nèi)存模型圖如下圖所示:
    Java內(nèi)存模型.png

    ??其中橙色部分為線程私有的數(shù)據(jù)區(qū)域,藍(lán)色部分為線程共享的數(shù)據(jù)區(qū)域
    程序計(jì)數(shù)器
    ??程序計(jì)數(shù)器是一塊較小的內(nèi)存空間,主要記錄當(dāng)前線程執(zhí)行的虛擬機(jī)字節(jié)碼地址,如果執(zhí)行的是Native方法,則程序計(jì)數(shù)器值為空。
    虛擬機(jī)棧
    ??虛擬機(jī)棧描述的是Java方法的內(nèi)存模型:每個(gè)方法在執(zhí)行的時(shí)候都會(huì)創(chuàng)建一個(gè)棧幀,用來存儲(chǔ)局部標(biāo)量表、操作數(shù)棧、動(dòng)態(tài)鏈接、方法出口等信息
    本地方法棧
    ??本地方法棧與虛擬機(jī)棧作用相似,不同的是本地方法棧是用于描述Native方法的內(nèi)存模型

    ??Java堆是Java虛擬機(jī)所管理內(nèi)存中最大的一塊,也是被所有線程共享的一塊內(nèi)存區(qū)域,該區(qū)域主要是存放對(duì)象實(shí)例。Java堆也是垃圾收集器的主要區(qū)域,從內(nèi)存回收的角度來看,由于現(xiàn)在收集器基本都采用分代收集算法,所以Java堆還可以細(xì)分為新生代和老年代,再細(xì)致一點(diǎn)的有Eden空間、From Survivor空間、To Survivor空間等
    方法區(qū)
    ??方法區(qū)也是被各個(gè)線程共享的內(nèi)存區(qū)域,主要用于存儲(chǔ)被虛擬機(jī)加載的類信息、常量靜態(tài)變量、即時(shí)編譯器編譯后的代碼等數(shù)據(jù)
  • Java虛擬機(jī)是如何操作這些區(qū)域的

結(jié)合代碼重點(diǎn)了解一下JVM運(yùn)行時(shí)數(shù)據(jù)區(qū),主要是虛擬機(jī)棧的分析

com.kons;

public class Test{
   public static void main(String[] args){
       int a=1;
       int b=2;
       int c=add(a,b);
   }
   
   public static int add(int a,int b){
       return a+b;
   }
}

首先Test類被編譯成class文件,通過類加載子系統(tǒng)加載到內(nèi)存中。然后,JVM會(huì)給執(zhí)行的線程分配程序計(jì)數(shù)器、虛擬機(jī)棧、以及本地方法棧,如圖所示:

虛擬機(jī)棧.png

當(dāng)執(zhí)行main方法的時(shí)候,會(huì)給main方法創(chuàng)建一個(gè)棧幀壓入虛擬機(jī)棧中,同理,當(dāng)執(zhí)行到add方法時(shí)也是如此,如圖所示:

入棧.png

棧幀內(nèi)部主要由局部變量,操作數(shù)棧,動(dòng)態(tài)鏈接以及方法出口等及部分組成,接下來結(jié)合class文件了解一下,這個(gè)棧幀具體是怎么工作的。

打開class文件所在文件夾,通過javap命令查看class文件

javap -c Test.class >test.txt

代碼如圖所示:

Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static int add(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: iadd
       3: ireturn

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iconst_2
       3: istore_2
       4: iload_1
       5: iload_2
       6: invokestatic  #2                  // Method add:(II)I
       9: istore_3
      10: return
}

執(zhí)行流程

iconst_1:將整數(shù)1推到操作數(shù)棧上
istore_1:棧頂元素出棧并存入局部變量表1號(hào)位
iconst_2:將整數(shù)2推到操作數(shù)棧上
istore_2:棧頂元素出棧并存入局部變量表2號(hào)位

stack.png

iload_1:將局部變量表1號(hào)位元素放入棧頂
iload_2:將局部變量表2號(hào)位元素放入棧頂

iload.png

invorkestatic:調(diào)用靜態(tài)方法add,該指令將彈出棧頂數(shù)據(jù)作為方法的參數(shù)并放入add棧幀中的局部變量表中

add.png

iload_0,iload_1:將局部變量表的數(shù)據(jù)壓入操作數(shù)棧

add_load.png

執(zhí)行到iadd的時(shí)候,操作數(shù)棧將數(shù)據(jù)相加并壓入棧,執(zhí)行完后,通過方法出口返回到main方法,并將add棧幀彈出虛擬機(jī)棧,最后通過istore指令將返回的數(shù)據(jù)存入局部變量表中

return.png

參考資料
《深入Java虛擬機(jī)》

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

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