-
Java虛擬機內(nèi)存
???Java虛擬機在執(zhí)行Java程序的時候會將它管理的內(nèi)存分為若干個不同的數(shù)據(jù)區(qū)域焙压。不同的區(qū)域用途也各不相同熔任,具體內(nèi)存模型圖如下圖所示:
Java內(nèi)存模型.png
??其中橙色部分為線程私有的數(shù)據(jù)區(qū)域,藍色部分為線程共享的數(shù)據(jù)區(qū)域
程序計數(shù)器
??程序計數(shù)器是一塊較小的內(nèi)存空間,主要記錄當前線程執(zhí)行的虛擬機字節(jié)碼地址,如果執(zhí)行的是Native方法,則程序計數(shù)器值為空鱼冀。
虛擬機棧
??虛擬機棧描述的是Java方法的內(nèi)存模型:每個方法在執(zhí)行的時候都會創(chuàng)建一個棧幀,用來存儲局部標量表悠就、操作數(shù)棧千绪、動態(tài)鏈接、方法出口等信息
本地方法棧
??本地方法棧與虛擬機棧作用相似梗脾,不同的是本地方法棧是用于描述Native方法的內(nèi)存模型
堆
??Java堆是Java虛擬機所管理內(nèi)存中最大的一塊荸型,也是被所有線程共享的一塊內(nèi)存區(qū)域,該區(qū)域主要是存放對象實例炸茧。Java堆也是垃圾收集器的主要區(qū)域瑞妇,從內(nèi)存回收的角度來看,由于現(xiàn)在收集器基本都采用分代收集算法梭冠,所以Java堆還可以細分為新生代和老年代辕狰,再細致一點的有Eden空間、From Survivor空間控漠、To Survivor空間等
方法區(qū)
??方法區(qū)也是被各個線程共享的內(nèi)存區(qū)域蔓倍,主要用于存儲被虛擬機加載的類信息、常量靜態(tài)變量、即時編譯器編譯后的代碼等數(shù)據(jù) - Java虛擬機是如何操作這些區(qū)域的
結(jié)合代碼重點了解一下JVM運行時數(shù)據(jù)區(qū)偶翅,主要是虛擬機棧的分析
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會給執(zhí)行的線程分配程序計數(shù)器、虛擬機棧爆价、以及本地方法棧垦巴,如圖所示:
當執(zhí)行main方法的時候,會給main方法創(chuàng)建一個棧幀壓入虛擬機棧中铭段,同理骤宣,當執(zhí)行到add方法時也是如此,如圖所示:
棧幀內(nèi)部主要由局部變量序愚,操作數(shù)棧憔披,動態(tài)鏈接以及方法出口等及部分組成,接下來結(jié)合class文件了解一下爸吮,這個棧幀具體是怎么工作的芬膝。
打開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號位
iconst_2
:將整數(shù)2推到操作數(shù)棧上
istore_2
:棧頂元素出棧并存入局部變量表2號位
iload_1
:將局部變量表1號位元素放入棧頂
iload_2
:將局部變量表2號位元素放入棧頂
invorkestatic
:調(diào)用靜態(tài)方法add形娇,該指令將彈出棧頂數(shù)據(jù)作為方法的參數(shù)并放入add棧幀中的局部變量表中
iload_0,iload_1
:將局部變量表的數(shù)據(jù)壓入操作數(shù)棧
執(zhí)行到iadd的時候锰霜,操作數(shù)棧將數(shù)據(jù)相加并壓入棧,執(zhí)行完后桐早,通過方法出口返回到main方法癣缅,并將add棧幀彈出虛擬機棧,最后通過istore指令將返回的數(shù)據(jù)存入局部變量表中
參考資料
《深入Java虛擬機》