jvm原理和代碼運行(xing)的過程
一次編譯,到處運行
java一(yi)直宣(xuan)傳的口號(hao)是(shi):一(yi)次編(bian)譯(yi),到處運(yun)行。那么它如何實(shi)現(xian)的呢?我(wo)們看下圖:
java程序經過一次編譯之后,將java代碼編譯為字節碼也就是class文件,然后在不同的操作系統上依靠不同的java虛擬機進行解釋,最后再轉換為不同平臺的機器碼,最終得到執行。這樣我們是不是可以推演,如果要在mac系統上運行,是不是只需要安裝mac java虛擬機就行(xing)了。那(nei)么(me)了解了這個基本原理后,我們來(lai)看(kan)一下,一段程序(xu)是如何執行(xing)的(de)。
public class HelloWorld {
public static void main(String[] args) {
System.out.print("Hello world");
}
}
這段程(cheng)序從(cong)編譯到(dao)運行,所經歷的過程(cheng)如下(xia):
jvm基本結構
可能通過上面(mian)的描述,大家(jia)對JVM運行流程有了(le)一個粗略的認識,那(nei)么(me)JVM內部到底是怎么(me)執行一個class文件的呢?
jvm內存分類介紹
JVM內存空間(jian)包含:方法區、java堆、java棧(zhan)、本(ben)地(di)方法棧(zhan)。
-
方法區是各個
線程共享的區域,存放類信息(xi)、常量、靜態變量。 -
java堆也是
線程共享的(de)(de)(de)區域(yu),我們的(de)(de)(de)類的(de)(de)(de)實(shi)例(li)就放在這個區域(yu),可(ke)以想象你的(de)(de)(de)一個系統(tong)會(hui)產生(sheng)很多(duo)實(shi)例(li),因此java堆的(de)(de)(de)空間也是最大的(de)(de)(de)。如果java堆空間不(bu)足(zu)了,程(cheng)序會(hui)拋(pao)出OutOfMemoryError異(yi)常。 -
java棧是每個
線程私有的區域,它的生命周期與線程相同,一個線程對應一個java棧,每執行一個方法就會往棧中壓入一個元素,這個元素叫“棧幀”,而棧幀中包括了(le)方法(fa)中的局部(bu)變量、用于存放中間狀態值(zhi)的操作(zuo)棧,如果java棧空間不足了(le),程(cheng)序會拋出(chu)StackOverflowError異(yi)常.
每個幀代(dai)表一個方(fang)法(fa),Java方(fang)法(fa)有兩種(zhong)返回方(fang)式,return和(he)拋出異常,兩種(zhong)方(fang)式都會導致該方(fang)法(fa)對應(ying)的幀出棧和(he)釋放內存(cun)。
-
本(ben)地方(fang)法棧角色(se)和(he)java棧類(lei)似,只不過它是用(yong)來表示執(zhi)行本(ben)地方(fang)法的(de),本(ben)地方(fang)法棧存(cun)放的(de)方(fang)法調(diao)用(yong)本(ben)地方(fang)法接口,最終(zhong)調(diao)用(yong)本(ben)地方(fang)法庫,實現(xian)與(yu)操作系(xi)統、硬件交互的(de)目的(de)。
-
PC寄(ji)存(cun)器(程序(xu)計(ji)數(shu)器),說(shuo)到這里我們的類已經加載(zai)了,實例對象、方法(fa)、靜態變量都去了自己改(gai)去的地方,那么問題來了,程序(xu)該(gai)怎(zen)么執行(xing)(xing),哪(na)個方法(fa)先執行(xing)(xing),哪(na)個方法(fa)后執行(xing)(xing),這些(xie)指令執行(xing)(xing)的順序(xu)就是PC寄(ji)存(cun)器在管,它的作用就是控(kong)制程序(xu)指令的執行(xing)(xing)順序(xu)。
執(zhi)行引(yin)擎當然(ran)就是根據PC寄(ji)存(cun)器調配的指令順序(xu),依(yi)次執(zhi)行程序(xu)指令。
- 靜態變量+常量+類信息+運行時常量池存在方法區中,實例變量存在堆內存中。
- 基本類型的變量和對象的引用變量都是在函數的棧內存中分