解讀JVM的生命周期是怎么樣的
JVM的生命周期是怎么樣的
JVM 的生命周期是指 JVM 實(shí)例從啟動(dòng)到終止的整個(gè)過(guò)程。
一個(gè) Java 應(yīng)用程序通常對(duì)應(yīng)一個(gè) JVM 實(shí)例(除非使用 JNI 等技術(shù)在同一進(jìn)程中創(chuàng)建多個(gè) JVM 實(shí)例,但這并不常見(jiàn))。
JVM 的生命周期階段
啟動(dòng) (Startup)
- 創(chuàng)建 JVM 實(shí)例: 當(dāng)你使用
java命令運(yùn)行 Java 程序時(shí),操作系統(tǒng)會(huì)創(chuàng)建一個(gè)新的進(jìn)程,并在該進(jìn)程中啟動(dòng)一個(gè) JVM 實(shí)例。 - 加載和初始化:
- 查找并加載 JDK: 找到 JRE (Java Runtime Environment) 的位置.
- 創(chuàng)建引導(dǎo)類加載器 (Bootstrap Class Loader): 加載核心類庫(kù)(
rt.jar等)。 - 創(chuàng)建擴(kuò)展類加載器 (Extension Class Loader) 和應(yīng)用程序類加載器 (Application Class Loader): 分別加載擴(kuò)展類庫(kù)和應(yīng)用程序的類。
- 加載
main方法所在的類: 使用應(yīng)用程序類加載器加載包含main方法的類。 - 初始化類: 執(zhí)行類的靜態(tài)初始化塊和靜態(tài)變量賦值。
- 命令行參數(shù): 解析傳入
java命令的參數(shù).
運(yùn)行 (Execution)
- 執(zhí)行
main方法: JVM 調(diào)用main方法,開始執(zhí)行 Java 程序。 - 類加載: 在程序運(yùn)行過(guò)程中,根據(jù)需要?jiǎng)討B(tài)加載類。
- 字節(jié)碼執(zhí)行: JVM 的執(zhí)行引擎解釋或編譯執(zhí)行字節(jié)碼。
- 內(nèi)存管理: JVM 分配和管理內(nèi)存,進(jìn)行垃圾回收。
- 線程管理: JVM 創(chuàng)建和管理線程。
- 異常處理: JVM 處理程序中發(fā)生的異常。
終止 (Termination)
正常終止:
- 當(dāng)程序執(zhí)行完
main方法,并且所有非守護(hù)線程(non-daemon threads)都已結(jié)束時(shí),JVM 正常終止。 - 可以通過(guò)調(diào)用
System.exit(status)方法顯式終止 JVM。status是退出狀態(tài)碼(0 表示正常退出,非 0 表示異常退出)。
異常終止:
- 如果程序中發(fā)生了未捕獲的異常,并且沒(méi)有設(shè)置默認(rèn)的未捕獲異常處理器,JVM 會(huì)異常終止。
- 可以通過(guò)
Thread.setDefaultUncaughtExceptionHandler()設(shè)置默認(rèn)的未捕獲異常處理器。
外部終止:
- 用戶可以通過(guò)操作系統(tǒng)命令(例如,在 Linux 中使用
kill命令)強(qiáng)制終止 JVM 進(jìn)程。 - JVM 可能會(huì)收到操作系統(tǒng)發(fā)送的終止信號(hào)(例如,SIGTERM)。
鉤子 (Shutdown Hooks):
- 在 JVM 終止之前,可以注冊(cè)一些鉤子函數(shù)(shutdown hooks),用于執(zhí)行一些清理操作(例如,關(guān)閉數(shù)據(jù)庫(kù)連接、釋放資源等)。
- 可以使用
Runtime.getRuntime().addShutdownHook(Thread hook)方法注冊(cè)鉤子函數(shù)。 - 鉤子函數(shù)會(huì)在以下情況下執(zhí)行:
- 程序正常退出。
- 調(diào)用
System.exit()。 - 用戶中斷程序(例如,按下 Ctrl+C)。
- 系統(tǒng)關(guān)閉。
- 鉤子函數(shù)執(zhí)行的順序是不確定的。
總結(jié)流程圖
+----------------+
| 啟動(dòng) JVM | (java 命令)
+----------------+
|
V
+----------------+
| 加載和初始化 |
| - 查找并加載 JDK |
| - 創(chuàng)建類加載器 |
| - 加載 main 類 |
| - 初始化類 |
+----------------+
|
V
+----------------+
| 運(yùn)行程序 |
| - 執(zhí)行 main 方法|
| - 類加載 |
| - 字節(jié)碼執(zhí)行 |
| - 內(nèi)存管理 |
| - 線程管理 |
| - 異常處理 |
+----------------+
|
V
+----------------+
| 終止 JVM |
| - 正常終止 |
| - 異常終止 |
| - 外部終止 |
| - 執(zhí)行鉤子函數(shù) |
+----------------+代碼示例 (演示鉤子函數(shù))
public class JVMLifecycle {
public static void main(String[] args) {
// 注冊(cè)鉤子函數(shù)
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("JVM 即將終止,執(zhí)行清理操作...");
// 在這里執(zhí)行清理操作 (例如,關(guān)閉數(shù)據(jù)庫(kù)連接、釋放資源等)
}));
System.out.println("程序開始執(zhí)行...");
// 模擬程序運(yùn)行一段時(shí)間
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程序執(zhí)行完畢...");
// 可以選擇顯式退出 (也可以不調(diào)用 exit,讓程序自然結(jié)束)
// System.exit(0);
}
}運(yùn)行結(jié)果:
程序開始執(zhí)行...
程序執(zhí)行完畢...
JVM 即將終止,執(zhí)行清理操作...
注意:
- 如果程序中存在死循環(huán)或無(wú)限等待,JVM 可能永遠(yuǎn)不會(huì)終止。
- 守護(hù)線程 (daemon thread) 不會(huì)阻止 JVM 終止。當(dāng)所有非守護(hù)線程都結(jié)束后,JVM 會(huì)強(qiáng)制終止所有守護(hù)線程。
- 鉤子函數(shù)應(yīng)該盡量簡(jiǎn)短,避免執(zhí)行耗時(shí)的操作,否則可能會(huì)導(dǎo)致 JVM 無(wú)法正常終止。
- 不要在鉤子函數(shù)中調(diào)用
System.exit(),否則會(huì)導(dǎo)致死循環(huán)。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
使用Spring @DependsOn控制bean加載順序的實(shí)例
這篇文章主要介紹了使用Spring @DependsOn控制bean加載順序的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07
Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例
這篇文章主要介紹了Spring使用@Autowired為抽象父類注入依賴代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
SpringBoot 動(dòng)態(tài)配置Profile環(huán)境的方式
這篇文章主要介紹了SpringBoot 動(dòng)態(tài)配置Profile環(huán)境的方式,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
MybatisPlus BaseMapper 中的方法全部 Invalid bound statement (not f
這篇文章主要介紹了MybatisPlus BaseMapper 中的方法全部 Invalid bound statement (not found)的Error處理方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09
小白也可以學(xué)會(huì)的Java NIO的Write事件
剛開始對(duì)NIO的寫操作理解的不深,不知道為什么要注冊(cè)寫事件,何時(shí)注冊(cè)寫事件,為什么寫完之后要取消注冊(cè)寫事件,今天特地整理了本篇文章,需要的朋友可以參考下2021-06-06
mysql數(shù)據(jù)庫(kù)忘記密碼時(shí)如何修改
本文主要介紹了mysql數(shù)據(jù)庫(kù)忘記密碼時(shí)如何修改的步驟方法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02
Java使用OpenCV實(shí)現(xiàn)實(shí)時(shí)對(duì)象追蹤的代碼示例
視覺(jué)跟蹤是指通過(guò)分析視頻幀來(lái)自動(dòng)追蹤一個(gè)或多個(gè)移動(dòng)對(duì)象的過(guò)程,這項(xiàng)技術(shù)廣泛應(yīng)用于監(jiān)控、人機(jī)交互、增強(qiáng)現(xiàn)實(shí)和自動(dòng)駕駛等領(lǐng)域,本文給大家介紹了Java如何使用OpenCV實(shí)現(xiàn)實(shí)時(shí)對(duì)象追蹤,需要的朋友可以參考下2025-09-09
springboot2.x整合shiro權(quán)限框架的使用
這篇文章主要介紹了springboot2.x整合shiro權(quán)限框架的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
java+SpringBoot設(shè)計(jì)實(shí)現(xiàn)評(píng)教系統(tǒng)
這篇文章主要介紹了用過(guò)Java SpringBoot實(shí)現(xiàn)一個(gè)簡(jiǎn)單的評(píng)價(jià)系統(tǒng),可以做到學(xué)生管理、教師管理、評(píng)教管理、指標(biāo)管理、課程管理等。感興趣的可以了解一下2021-12-12

