網(wǎng)站開發(fā)技術(shù)路線百度競價(jià)冷門產(chǎn)品
1.加載(Loading):
在加載階段,JVM會(huì)找到并加載Java字節(jié)碼文件。加載階段分為三個(gè)步驟:通過類的全限定名找到對應(yīng)的字節(jié)碼文件,創(chuàng)建一個(gè)與該類相關(guān)的Class對象,將類的靜態(tài)數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)在方法區(qū)中。加載完成后,JVM內(nèi)存中就存在了一個(gè)Class對象,它包含了該類的所有屬性和方法的信息。
2.驗(yàn)證(Verification):
驗(yàn)證階段是確保加載的字節(jié)碼文件符合JVM規(guī)范的過程。在驗(yàn)證階段,JVM會(huì)檢查字節(jié)碼的格式、語義以及符號引用的正確性,以防止安全漏洞和運(yùn)行時(shí)錯(cuò)誤。驗(yàn)證的目標(biāo)包括:類文件結(jié)構(gòu)的完整性、語義的正確性和符號引用的驗(yàn)證。
3.準(zhǔn)備(Preparation):
在準(zhǔn)備階段,JVM會(huì)為類的靜態(tài)變量分配內(nèi)存并設(shè)置默認(rèn)初始值。這些靜態(tài)變量包括基本數(shù)據(jù)類型和引用類型,它們會(huì)被初始化為零值(零值是每種數(shù)據(jù)類型的默認(rèn)值,如0、false、null等),而不是類中定義的初始值。此階段會(huì)在方法區(qū)中為每個(gè)靜態(tài)變量分配內(nèi)存空間。
4.解析(Resolution):
解析階段是將符號引用轉(zhuǎn)換為直接引用的過程。在Java中,類的方法和字段訪問采用的是符號引用,而不是直接引用。解析階段會(huì)將這些符號引用轉(zhuǎn)化為直接引用,以便能夠正確訪問和調(diào)用類的方法和字段。解析階段包括類、字段和方法的解析。
5.初始化(Initialization):
初始化階段是JVM執(zhí)行類的初始化代碼的過程。類的初始化代碼包括靜態(tài)變量的賦值和靜態(tài)代碼塊的執(zhí)行。在該階段,JVM會(huì)按照類的加載順序依次初始化每個(gè)類,確保所有的靜態(tài)變量被正確初始化,并執(zhí)行靜態(tài)代碼塊中的代碼。初始化階段是類加載過程的最后一步。
6.使用(Usage):
使用階段是指JVM執(zhí)行Java程序的過程。在使用階段,JVM會(huì)按照程序的流程執(zhí)行相應(yīng)的指令,并處理方法調(diào)用和對象創(chuàng)建等操作。JVM通過執(zhí)行Java字節(jié)碼來實(shí)際運(yùn)行程序,包括調(diào)用方法、訪問字段和創(chuàng)建對象等操作。
7.卸載(Unloading):
卸載階段是指JVM從內(nèi)存中卸載不再被使用的類和相關(guān)資源。當(dāng)一個(gè)類不再被引用,并且沒有正在執(zhí)行的對象實(shí)例時(shí),JVM會(huì)卸載該類,并釋放其占用的內(nèi)存空間。卸載過程由垃圾回收器完成,它會(huì)檢測并回收不再被引用的類和對象。
JVM的生命周期是一個(gè)動(dòng)態(tài)的過程,它負(fù)責(zé)加載、驗(yàn)證、準(zhǔn)備、解析、初始化、使用和卸載Java字節(jié)碼文件。每個(gè)階段都有特定的任務(wù)和目標(biāo),保證程序能夠正確運(yùn)行并在不再需要時(shí)釋放資源。
Java虛擬機(jī)(JVM)的啟動(dòng)和執(zhí)行過程分為以下幾個(gè)步驟:
-
加載:JVM首先加載JDK的核心類庫以及應(yīng)用程序所需的其他類。加載過程中包括以下幾種方式:
- 類文件加載:將編譯后的Java類文件加載到內(nèi)存中。
- 字節(jié)碼校驗(yàn):驗(yàn)證加載的字節(jié)碼是否符合Java語法規(guī)范。
- 字節(jié)碼轉(zhuǎn)換:將字節(jié)碼轉(zhuǎn)換成機(jī)器碼,以便于執(zhí)行。
-
鏈接:在加載完類文件后,JVM需要進(jìn)行鏈接處理,包括以下三個(gè)階段:
- 驗(yàn)證:檢查字節(jié)碼是否符合JVM規(guī)范。
- 準(zhǔn)備:為類變量(靜態(tài)變量)分配內(nèi)存空間,并設(shè)置默認(rèn)初始值。
- 解析:將符號引用轉(zhuǎn)換為直接引用。
-
初始化:執(zhí)行類的初始化代碼,包括靜態(tài)變量的賦值和靜態(tài)代碼塊的執(zhí)行。JVM保證類的初始化在多線程環(huán)境下的安全性。
-
執(zhí)行:將字節(jié)碼轉(zhuǎn)換為機(jī)器碼,逐行執(zhí)行機(jī)器碼指令。執(zhí)行過程中需要注意以下幾點(diǎn):
- 進(jìn)行即時(shí)編譯(Just-In-Time Compilation):將熱點(diǎn)代碼(被頻繁調(diào)用的代碼)編譯成機(jī)器碼,以提高執(zhí)行效率。
- 垃圾回收(Garbage Collection):在執(zhí)行過程中,JVM會(huì)自動(dòng)回收不再使用的內(nèi)存空間,以確保內(nèi)存的有效利用。
-
銷毀:當(dāng)Java程序執(zhí)行完畢或者出現(xiàn)異常時(shí),JVM會(huì)釋放所有占用的資源,并終止執(zhí)行。
JVM的啟動(dòng)和執(zhí)行流程可以總結(jié)為:加載類文件、鏈接處理、初始化類、執(zhí)行字節(jié)碼。通過這一流程,JVM能夠?qū)崿F(xiàn)Java程序的跨平臺運(yùn)行,并提供內(nèi)存管理和垃圾回收等功能,以確保程序的安全和性能。
JVM(Java Virtual Machine)的退出流程可以分為正常退出和非正常退出兩種情況。
-
正常退出:
- JVM收到終止請求,如通過調(diào)用System.exit()方法或者通過kill命令結(jié)束進(jìn)程。
- JVM開始執(zhí)行退出過程,首先會(huì)執(zhí)行已注冊的關(guān)閉鉤子(Shutdown Hook)。
- 關(guān)閉鉤子是一段在JVM正常退出之前執(zhí)行的代碼,可以通過Runtime.addShutdownHook方法注冊。
- JVM的關(guān)閉鉤子可以用于釋放資源、保存狀態(tài)等操作。
- 在關(guān)閉鉤子執(zhí)行完畢后,JVM執(zhí)行一些清理操作,如垃圾回收、關(guān)閉網(wǎng)絡(luò)連接等。
- 最后,JVM完全終止運(yùn)行,進(jìn)程退出。
-
非正常退出:
- JVM遇到致命錯(cuò)誤,如OutOfMemoryError或StackOverflowError。
- JVM無法繼續(xù)執(zhí)行,并拋出一個(gè)異常。
- 異常的拋出會(huì)導(dǎo)致程序所在的線程被終止,然后整個(gè)JVM進(jìn)程退出。
JVM的退出過程可以通過實(shí)現(xiàn)一個(gè)Shutdown Hook來觀察,示例代碼如下:
public class ShutdownHookExample {public static void main(String[] args) {// 注冊一個(gè)關(guān)閉鉤子Runtime.getRuntime().addShutdownHook(new Thread() {@Overridepublic void run() {System.out.println("Shutting down...");}});// 模擬程序運(yùn)行try {Thread.sleep(5000); // 程序休眠5秒鐘} catch (InterruptedException e) {e.printStackTrace();}// 手動(dòng)觸發(fā)退出事件System.exit(0);}
}
該示例程序在運(yùn)行時(shí)注冊了一個(gè)關(guān)閉鉤子,并在關(guān)閉鉤子中打印一條消息。然后程序會(huì)休眠5秒鐘,之后手動(dòng)調(diào)用System.exit(0)方法觸發(fā)JVM退出事件。在程序運(yùn)行時(shí),我們可以觀察到在5秒后打印的"Shutting down..."消息,表示關(guān)閉鉤子被執(zhí)行。然后JVM會(huì)繼續(xù)執(zhí)行清理操作并退出。
需要注意的是,關(guān)閉鉤子的執(zhí)行順序是不確定的,不同的鉤子可能在不同的線程中執(zhí)行。因此,如果有多個(gè)關(guān)閉鉤子,它們之間應(yīng)該是獨(dú)立的,不依賴于其他鉤子的執(zhí)行順序。