制作視頻網(wǎng)站開發(fā)電商關(guān)鍵詞工具
概述
Java虛擬機(jī)(JVM)是Java程序運(yùn)行的核心,其中類加載器和雙親委派模型是JVM的重要組成部分。本文將深入討論這兩個概念,并解釋它們在實(shí)際開發(fā)中的應(yīng)用。
1. 什么是類加載器?
類加載器是JVM的一部分,負(fù)責(zé)加載Java類的字節(jié)碼文件。Java應(yīng)用程序中的每個類都必須由類加載器加載,類加載器將類的字節(jié)碼文件從磁盤或網(wǎng)絡(luò)加載到內(nèi)存中,并在JVM中創(chuàng)建一個對應(yīng)的Class對象。
類加載器工作原理示意圖
2. 什么是雙親委派模型?
雙親委派模型是一種類加載器之間的層次結(jié)構(gòu),它通過父類加載器委派給子類加載器加載類。當(dāng)一個類需要被加載時,首先會請求父類加載器加載,只有當(dāng)父類加載器無法加載時,才由子類加載器嘗試加載。這種層次結(jié)構(gòu)有助于保持類的唯一性,防止重復(fù)加載,提高安全性。
詳解原理分析
1. 類加載器的工作原理
類加載器按照三個階段加載類:加載、連接和初始化。加載器根據(jù)類的全名定位類的二進(jìn)制字節(jié)流,然后將其轉(zhuǎn)化為Class對象。
類的加載過程
/*** 類加載子系統(tǒng) * */
public class HelloLoader {public static void main(String[] args) {System.out.println("類加載....");}
}
加載階段
獲取類的二進(jìn)制字節(jié)流
- 通過類的全限定名獲取定義此類的二進(jìn)制字節(jié)流。
轉(zhuǎn)化為方法區(qū)的運(yùn)行時數(shù)據(jù)結(jié)構(gòu)
- 將字節(jié)流代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時數(shù)據(jù)結(jié)構(gòu)。
生成java.lang.Class對象
- 在內(nèi)存中生成一個代表這個類的
java.lang.Class
對象,作為方法區(qū)這個類的訪問入口。
加載class文件的方式
- 本地系統(tǒng)中直接加載
- 通過網(wǎng)絡(luò)獲取(Web Applet)
- 從zip壓縮包中讀取(基礎(chǔ)為jar、war格式)
- 運(yùn)行時計算生成(動態(tài)代理技術(shù))
- 由其他文件生成(JSP應(yīng)用從數(shù)據(jù)庫提取)
- 從加密文件中獲取(防Class文件反編譯保護(hù))
鏈接階段
驗(yàn)證(Verify)
- 目的:確保Class文件的字節(jié)流中包含信息符合虛擬機(jī)要求,保證加載的類正確性,不危害虛擬機(jī)自身安全。
- 驗(yàn)證包括文件格式驗(yàn)證、元數(shù)據(jù)驗(yàn)證、字節(jié)碼驗(yàn)證、符號引用驗(yàn)證。
準(zhǔn)備(Prepare)
- 為類變量分配內(nèi)存并設(shè)置默認(rèn)初始值,即零值。
- 類變量會分配在方法區(qū)中。
- 不包含使用
final
修飾的static,因?yàn)閒inal在編譯時就分配并顯式初始化。- 實(shí)例變量隨對象分配到Java堆中。
解析(Resolve)
- 將常量池內(nèi)的符號引用轉(zhuǎn)換為直接引用。
- 解析操作通常在初始化之后執(zhí)行。
- 解析針對類、字段、類方法、接口方法、方法類型等。
初始化階段
- 執(zhí)行類構(gòu)造器<clinit>()的過程,該方法由編譯器自動收集類中的類變量賦值動作和靜態(tài)代碼塊中的語句合并而來。
- 靜態(tài)變量在準(zhǔn)備階段賦初值,初始化階段才是實(shí)際值。
- 初始化順序按源文件中出現(xiàn)的順序執(zhí)行。
- 父類的<clinit>()在子類的<clinit>()之前執(zhí)行,確保父類初始化完畢。
類加載器分類
啟動類加載器(Bootstrap ClassLoader)
- 加載核心庫,不繼承ClassLoader,父加載器為null。
- 加載java、javax、sun等開頭的類。
擴(kuò)展類加載器(Extension ClassLoader)
- 加載擴(kuò)展目錄中的類庫。
應(yīng)用程序類加載器(AppClassLoader)
- 加載classpath或系統(tǒng)屬性java.class.path指定路徑下的類庫。
- 系統(tǒng)默認(rèn)的類加載器。
用戶自定義類加載器
- 通過繼承ClassLoader實(shí)現(xiàn),用于隔離加載類、修改加載方式、擴(kuò)展加載源、防止源碼泄漏。
2. 雙親委派模型的工作流程
- 當(dāng)一個類加載器收到加載請求時,首先檢查自己是否已經(jīng)加載了這個類。
- 如果已加載,則直接返回Class對象。
- 如果未加載,則將加載請求委派給父類加載器。
- 這一過程一直遞歸進(jìn)行,直到根加載器,如果根加載器仍未加載,則由當(dāng)前加載器加載類。
怎么打破雙親委派模型?
打破雙親委派機(jī)制則不僅要繼承ClassLoader類,還要重寫loadClass和findClass方法。
知識點(diǎn)在實(shí)際開發(fā)的應(yīng)用
1. 模塊化開發(fā)
雙親委派模型在模塊化開發(fā)中得到廣泛應(yīng)用。通過將不同的功能模塊交給不同的類加載器加載,可以有效隔離模塊之間的類,確保模塊的獨(dú)立性。
案例詳解:
假設(shè)我們有一個大型電商應(yīng)用,分為用戶模塊、訂單模塊和支付模塊。每個模塊有自己的類加載器,負(fù)責(zé)加載模塊內(nèi)的類。這種模塊化的設(shè)計可以使得每個模塊獨(dú)立開發(fā)、測試和部署,降低了系統(tǒng)的耦合性。
2. 動態(tài)加載
類加載器的靈活性使得在運(yùn)行時動態(tài)加載類成為可能。這在某些框架和插件系統(tǒng)中得到了廣泛應(yīng)用,使系統(tǒng)更具可擴(kuò)展性。
案例詳解:
考慮一個圖形編輯器的插件系統(tǒng),用戶可以根據(jù)需要選擇性地加載不同的插件。每個插件都由一個獨(dú)立的類加載器加載,這樣用戶可以在運(yùn)行時添加或移除插件,無需重新啟動編輯器。
總結(jié)
本文深入探討了JVM中的類加載器和雙親委派模型,通過示意圖等多種呈現(xiàn)形式,從概念到原理再到實(shí)際應(yīng)用進(jìn)行了全方位的講解。了解這些知識對于理解Java程序的運(yùn)行機(jī)制,優(yōu)化性能以及實(shí)現(xiàn)模塊化開發(fā)和動態(tài)加載都具有重要意義。通過深入學(xué)習(xí)這些內(nèi)容,開發(fā)者可以更好地利用JVM的特性,寫出更健壯、高效的Java應(yīng)用程序。