一個(gè)Java的main方法在JVM中的執(zhí)行流程示例詳解
一個(gè)Java的main方法在JVM中的執(zhí)行流程可以分為??四大階段??:??加載 -> 鏈接 -> 初始化 -> 執(zhí)行??。
// HelloWorld.java
public class HelloWorld {
public static void main(String[] args) {
String message = "Hello, JVM!";
System.out.println(message);
}
}第一階段:加載 (Loading)
??目標(biāo):找到并加載類的二進(jìn)制數(shù)據(jù)。??
1.??編譯??:你執(zhí)行 javac HelloWorld.java。Java編譯器將源代碼編譯成JVM能理解的字節(jié)碼,存儲(chǔ)在 HelloWorld.class文件中。這個(gè)文件包含了一個(gè)??類常量池(Constant Pool)??,里面有各種符號(hào)引用,比如 Hello, JVM!這個(gè)字符串的字面量、System/out/println等類名、方法名和字段名。
2.??啟動(dòng)JVM??:你執(zhí)行 java HelloWorld。操作系統(tǒng)會(huì)啟動(dòng)JVM進(jìn)程。
3.??尋找類??:JVM通過(guò)??類加載器(ClassLoader)?? 來(lái)加載 HelloWorld類。
• Bootstrap ClassLoader??:首先,啟動(dòng)類加載器會(huì)去加載JAVA_HOME/lib下的核心類庫(kù),如 java.lang包(包括Object, String, System等)。
• Application ClassLoader??:然后,應(yīng)用程序類加載器開(kāi)始工作,它在你的CLASSPATH(默認(rèn)是當(dāng)前目錄)下尋找 HelloWorld.class文件。
4.??創(chuàng)建Class對(duì)象??:JVM成功讀取 HelloWorld.class的二進(jìn)制字節(jié)流后,會(huì)將其轉(zhuǎn)換為??方法區(qū)(Metaspace)?? 中的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu),并同時(shí)在 ??Java堆(Heap)?? 中創(chuàng)建一個(gè) java.lang.Class對(duì)象,作為方法區(qū)這些數(shù)據(jù)的訪問(wèn)入口。這個(gè) Class對(duì)象封裝了類的所有元信息(如方法、字段等)。
第二階段:鏈接 (Linking)
??目標(biāo):將加載到方法區(qū)的二進(jìn)制數(shù)據(jù)合并到JVM運(yùn)行時(shí)狀態(tài)中。?? 此階段細(xì)分為三步:
1.??驗(yàn)證 (Verification)??:JVM會(huì)嚴(yán)格檢查 HelloWorld.class文件的格式、元數(shù)據(jù)、字節(jié)碼等是否符合規(guī)范且不會(huì)危害JVM自身安全。這是一個(gè)非常重要的安全屏障。
2.??準(zhǔn)備 (Preparation)??:JVM為??類的靜態(tài)變量(static variables)?? 在方法區(qū)分配內(nèi)存并設(shè)置??初始值??(零值)。注意,這里是初始值,不是代碼中賦的值。
•例如,如果類里有 static int value = 123;,在準(zhǔn)備階段,value會(huì)被賦值為 0。真正的賦值 123要等到后面的初始化階段。
3.解析 (Resolution)??:JVM將??類常量池??中的??符號(hào)引用(Symbolic References)?? 替換為??直接引用(Direct References)??。
•符號(hào)引用??:就是一種約定好的形式來(lái)表示引用的目標(biāo),比如 java/lang/System.out。
•直接引用??:就是一個(gè)直接指向目標(biāo)的指針、偏移量或句柄。
•例如,在這一步,System.out這個(gè)符號(hào)引用會(huì)被解析為 java.io.PrintStream對(duì)象在堆內(nèi)存中的實(shí)際地址。
第三階段:初始化 (Initialization)
??目標(biāo):執(zhí)行類的構(gòu)造器 <clinit>()方法,為靜態(tài)變量賦予程序設(shè)定的初始值。??
1.到了這一步,JVM才開(kāi)始真正執(zhí)行你寫在Java代碼中的靜態(tài)語(yǔ)句和靜態(tài)變量賦值。
2.JVM會(huì)收集類中的所有??靜態(tài)變量的賦值動(dòng)作??和??靜態(tài)代碼塊(static {})??,合并生成一個(gè)唯一的 <clinit>()方法。
3.JVM會(huì)確保 <clinit>()方法在多線程環(huán)境下被正確地加鎖同步執(zhí)行,所以類初始化是線程安全的。
4.在我們的 HelloWorld例子中,沒(méi)有靜態(tài)變量和靜態(tài)代碼塊,所以 <clinit>()方法是空的,但這一步依然會(huì)發(fā)生。
第四階段:執(zhí)行 (Execution & Runtime)
??目標(biāo):創(chuàng)建線程,執(zhí)行字節(jié)碼。??
1 . 主線程??:JVM會(huì)為 main方法創(chuàng)建一個(gè)??主線程??。該線程擁有自己的??程序計(jì)數(shù)器(PC)?? 和 ??Java虛擬機(jī)棧(JVM Stack)??。
2 .?? 棧幀??:線程的每個(gè)方法調(diào)用都會(huì)在虛擬機(jī)棧中創(chuàng)建一個(gè)??棧幀(Stack Frame)??,用于存儲(chǔ)??局部變量表??、??操作數(shù)棧??、??動(dòng)態(tài)鏈接??、??方法返回地址??等信息。main方法是程序入口,所以第一個(gè)被壓入棧的棧幀就是 main方法的棧幀。
3 .? ?執(zhí)行引擎??:JVM的??執(zhí)行引擎??開(kāi)始解釋執(zhí)行 main方法棧幀中的字節(jié)碼。
String message = "Hello, JVM!";
執(zhí)行引擎遇到字面量 "Hello, JVM!"時(shí),會(huì)去??字符串常量池(String Table,位于堆中)?? 中尋找。如果找不到,就在堆中創(chuàng)建一個(gè)String對(duì)象并將其引用駐留在常量池中,然后將該引用存入 main棧幀的局部變量表 message中。
System.out.println(message);
執(zhí)行引擎通過(guò)之前在??解析階段??已經(jīng)轉(zhuǎn)換好的??直接引用??,快速地找到 System.out對(duì)應(yīng)的 PrintStream對(duì)象。
然后調(diào)用該對(duì)象的 println方法,將局部變量 message的引用(指向堆中的String對(duì)象)作為參數(shù)傳入。
4 .?? 本地方法調(diào)用??:println方法底層是一個(gè)??本地方法(Native Method)??,調(diào)用的是操作系統(tǒng)本身的IO能力,將字符串輸出到控制臺(tái)。
5 .?? 方法返回??:main方法執(zhí)行完畢,其棧幀從虛擬機(jī)棧中彈出。主線程結(jié)束。
6 .?? JVM退出??:所有??非守護(hù)線程??都結(jié)束后,JVM進(jìn)程終止。
總結(jié)
到此這篇關(guān)于一個(gè)Java的main方法在JVM中執(zhí)行流程的文章就介紹到這了,更多相關(guān)JVM中main方法執(zhí)行流程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring?Boot與Spring?MVC?Spring對(duì)比及核心概念
這篇文章主要為大家介紹了Spring?Boot與Spring?MVC?Spring的對(duì)比以及你需要了解的核心概念,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-03-03
線程池中execute與submit的區(qū)別說(shuō)明
這篇文章主要介紹了線程池execute與submit的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot項(xiàng)目嵌入RocketMQ的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot項(xiàng)目嵌入RocketMQ的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-05-05
Java System.currentTimeMillis()時(shí)間的單位轉(zhuǎn)換與計(jì)算方式案例詳解
這篇文章主要介紹了Java System.currentTimeMillis()時(shí)間的單位轉(zhuǎn)換與計(jì)算方式案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08
為什么Java是程序員受歡迎的語(yǔ)言這幾個(gè)原因你該清楚
Java一直穩(wěn)居程序員很受歡迎的編程語(yǔ)言的榜首,是企業(yè)中使用最廣泛的編程語(yǔ)言。這篇文章主要介紹了為什么Java是程序員受歡迎的語(yǔ)言這幾個(gè)原因你該清楚,需要的朋友可以參考下2020-07-07
基于Java匯總Spock框架Mock靜態(tài)資源經(jīng)驗(yàn)
這篇文章主要介紹了基于Java匯總Spock框架Mock靜態(tài)資源經(jīng)驗(yàn),前面講了?Spock框架Mock對(duì)象、方法經(jīng)驗(yàn)總結(jié),今天分享一下Spock框架中Mock靜態(tài)資源的實(shí)踐經(jīng)驗(yàn)匯總。分成靜態(tài)資源和混合場(chǎng)景,需要的朋友可以參考一下2022-02-02
SpringBoot監(jiān)聽(tīng)器的實(shí)現(xiàn)示例
在SpringBoot中,你可以使用監(jiān)聽(tīng)器來(lái)響應(yīng)特定的事件,本文主要介紹了SpringBoot監(jiān)聽(tīng)器的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-12-12

