Java 程序在 JVM 中是怎樣執(zhí)行的?
我們都知道 Java 程序是運行在 JVM 中的。但你可能不知道一個 Java 程序在 JVM 中是怎樣執(zhí)行的。今天,就和大家來一探究竟。
首先,來看一下 JVM 的運行時數(shù)據(jù)區(qū)域劃分:

程序計數(shù)器:字節(jié)碼執(zhí)行指示器,實時記錄字節(jié)碼執(zhí)行的行號,線程私有。
虛擬機棧:也是線程私有的,它主要用來為方法提供服務(wù)。一個方法被執(zhí)行的時候,會創(chuàng)建一個棧幀,用來存放局部變量表、方法出口等信息。方法被調(diào)用時棧幀入棧,執(zhí)行結(jié)束時棧幀出棧。
本地方法棧:與虛擬機棧類似,只不過它的服務(wù)對象是本地(Native)方法。
堆:堆可謂是與程序員打交道最多的一塊區(qū)域了,也是 JVM 中最大的一塊內(nèi)存區(qū)域了。它里面主要用來存放的就是對象,垃圾回收主要就是針對這個區(qū)域。
對于程序員來說,堆和棧(虛擬機棧)是與我們關(guān)系最緊密的部分。面向?qū)ο蟮暮诵某蓡T就是對象和對象的行為(也就是方法),而堆和棧剛好是管著兩塊兒的。
讓我們回到標題中提出的問題:Java 程序在 JVM 中是怎樣執(zhí)行的呢?先看一段很簡單的代碼:
代碼很簡單,一個類,main() 方法調(diào)用 a() 方法,a() 方法中定義了一個 int 變量 a,然后調(diào)用 b() 方法,b() 方法中 new 了一個 User 對象 b。
想要弄明白這個問題,你需要一丟丟的前置知識:
棧中的局部變量表用于存放 Java 的基本類型和引用類型
實例對象存放在堆內(nèi),棧中有對應(yīng)的引用類型指向該實例的內(nèi)存地址
OK,下面用一個動畫來展示一下上面那段代碼是如何在 JVM 中運行的:

程序運行
main() 方法入棧
a() 方法被調(diào)用,入棧
基本類型 a 變量在棧中被創(chuàng)建
b() 方法被調(diào)用,入棧
引用類型 b 在棧中被創(chuàng)建
User 類型的實例在堆中被創(chuàng)建
將 User 實例的內(nèi)存地址指向引用類型 b
b() 方法執(zhí)行結(jié)束,b 變量銷毀,斷開對 User 實例的引用,出棧
a() 方法執(zhí)行結(jié)束,a 變量銷毀,出棧
垃圾回收將不再被引用的 User 實例回收掉
main() 方法執(zhí)行結(jié)束,出棧
程序執(zhí)行結(jié)束
打完收工。技術(shù)聊完了,下面我們聊點正事兒!

咳咳,趁著現(xiàn)在粉絲還不是太多,給早期關(guān)注的讀者送點福利,關(guān)注「做個開發(fā)者」公眾號。
做個開發(fā)者做一個純粹的開發(fā)者。12篇原創(chuàng)內(nèi)容公眾號
在公眾號的文章下方留言,獲贊最多的三位讀者每人送一本我的新書《Spring Boot趣味實戰(zhàn)課》,七月三十一號開獎。
另外,這次活動是雙管齊下,公眾號和微博同步進行。且兩個活動可以累加,如果你都參加,那么中獎幾率直接翻倍。并且支持定制簽名(如果不嫌我字丑,哈哈)。
微博上的活動也很簡單,關(guān)注「@水鏡不酷」并轉(zhuǎn)發(fā)下圖中的微博即可。

對了,如果你真的中了兩本,可以將其中一本兌換成現(xiàn)金,按照目前京東促銷價折算為 60 微信紅包(目前京東到手 57.8 元)。行了,別的不多說了大家?guī)兔D(zhuǎn)發(fā)一下吧。