JVM中類(lèi)的裝載是由類(lèi)加載器(ClassLoader)和它的子類(lèi)來(lái)實(shí)現(xiàn)的,Java中的類(lèi)加載器是一個(gè)重要的Java運(yùn)行時(shí)系統(tǒng)組件,它負(fù)責(zé)在運(yùn)行時(shí)查找和裝入類(lèi)文件中的類(lèi)歌憨。
由于Java的跨平臺(tái)性,經(jīng)過(guò)編譯的Java源程序并不是一個(gè)可執(zhí)行程序,而是一個(gè)或多個(gè)類(lèi)文件案铺。當(dāng)Java程序需要使用某個(gè)類(lèi)時(shí),JVM會(huì)確保這個(gè)類(lèi)已經(jīng)被加載梆靖、連接(驗(yàn)證控汉、準(zhǔn)備和解析)和初始化。類(lèi)的加載是指把類(lèi)的.class文件中的數(shù)據(jù)讀入到內(nèi)存中返吻,通常是創(chuàng)建一個(gè)字節(jié)數(shù)組讀入.class文件姑子,然后產(chǎn)生與所加載類(lèi)對(duì)應(yīng)的Class對(duì)象。加載完成后测僵,Class對(duì)象還不完整街佑,所以此時(shí)的類(lèi)還不可用。當(dāng)類(lèi)被加載后就進(jìn)入連接階段捍靠,這一階段包括驗(yàn)證沐旨、準(zhǔn)備(為靜態(tài)變量分配內(nèi)存并設(shè)置默認(rèn)的初始值)和解析(將符號(hào)引用替換為直接引用)三個(gè)步驟。最后JVM對(duì)類(lèi)進(jìn)行初始化榨婆,包括:1)如果類(lèi)存在直接的父類(lèi)并且這個(gè)類(lèi)還沒(méi)有被初始化磁携,那么就先初始化父類(lèi);2)如果類(lèi)中存在初始化語(yǔ)句纲辽,就依次執(zhí)行這些初始化語(yǔ)句颜武。
類(lèi)的加載是由類(lèi)加載器完成的,類(lèi)加載器包括:根加載器(BootStrap)拖吼、擴(kuò)展加載器(Extension)鳞上、系統(tǒng)加載器(System)和用戶自定義類(lèi)加載器(java.lang.ClassLoader的子類(lèi))。從Java 2(JDK 1.2)開(kāi)始吊档,類(lèi)加載過(guò)程采取了父親委托機(jī)制(PDM)篙议。PDM更好的保證了Java平臺(tái)的安全性,在該機(jī)制中怠硼,JVM自帶的Bootstrap是根加載器鬼贱,其他的加載器都有且僅有一個(gè)父類(lèi)加載器。類(lèi)的加載首先請(qǐng)求父類(lèi)加載器加載香璃,父類(lèi)加載器無(wú)能為力時(shí)才由其子類(lèi)加載器自行加載这难。JVM不會(huì)向Java程序提供對(duì)Bootstrap的引用。下面是關(guān)于幾個(gè)類(lèi)加載器的說(shuō)明:
Bootstrap:一般用本地代碼實(shí)現(xiàn)葡秒,負(fù)責(zé)加載JVM基礎(chǔ)核心類(lèi)庫(kù)(rt.jar)姻乓;
Extension:從java.ext.dirs系統(tǒng)屬性所指定的目錄中加載類(lèi)庫(kù)嵌溢,它的父加載器是Bootstrap;
System:又叫應(yīng)用類(lèi)加載器蹋岩,其父類(lèi)是Extension赖草。它是應(yīng)用最廣泛的類(lèi)加載器。它從環(huán)境變量classpath或者系統(tǒng)屬性java.class.path所指定的目錄中記載類(lèi)剪个,是用戶自定義加載器的默認(rèn)父加載器秧骑。