1.類加載機(jī)制
1.1什么是類的加載
類的加載是將.class文件中的二進(jìn)制數(shù)據(jù)讀到內(nèi)存中集惋,并把它放到運(yùn)行時(shí)數(shù)據(jù)區(qū)的方法區(qū)中校镐,在堆區(qū)創(chuàng)建一個java.lang.Class對象窖梁,用來封裝類在方法區(qū)中的數(shù)據(jù)結(jié)構(gòu)瞪慧。
- 類加載的最終產(chǎn)品:class對象
- 類加載時(shí)機(jī):jvm預(yù)知它要被使用到的時(shí)候
1.2類的生命周期
加載
查找并加載類的二進(jìn)制數(shù)據(jù),包括
- 通過類的全限定名獲得該類的二進(jìn)制字節(jié)流數(shù)據(jù)
- 將這個字節(jié)流代表的靜態(tài)存儲結(jié)構(gòu)轉(zhuǎn)為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)
- 在堆中生成一個代表這個類的class對象茅主,做外外部訪問方法區(qū)中數(shù)據(jù)的入口
驗(yàn)證
確保被加載的class類的字節(jié)流符合jvm的要求舞痰,大概完成4個階段的驗(yàn)證動作
- 文件格式驗(yàn)證
- 元數(shù)據(jù)驗(yàn)證
- 字節(jié)碼驗(yàn)證
- 符號引用驗(yàn)證
準(zhǔn)備
為類的靜態(tài)變量分配內(nèi)存,初始化成默認(rèn)值诀姚,這些在方法區(qū)中分配
- 僅僅對類變量(static)分配內(nèi)存响牛,不包括實(shí)例變量,實(shí)例變量在實(shí)例化時(shí)伴隨對象一起分配
- 這里說的初始值是數(shù)據(jù)類型默認(rèn)零值(0赫段、null呀打、false等),不是被顯示賦予的值
解析
jvm將常量池內(nèi)的符號引用替換為直接飲用的過程瑞佩,針對類聚磺、接口坯台、字段炬丸、類方法、接口方法蜒蕾、方法類型稠炬、方法句柄。
- 符號引用:以一組符號描述所引用對象咪啡,與jvm的內(nèi)存布局無關(guān)首启。
- 直接飲用:直接指向目標(biāo)的指針、相對偏移撤摸、句柄毅桃,與jvm內(nèi)存布局相關(guān)。
初始化
為類的靜態(tài)變量賦予正確的初始值准夷,真正開始執(zhí)行Java程序代碼(字節(jié)碼)钥飞。初始化步驟:
- 如果這個類還沒有被加載和連接,先加載連接這個類衫嵌;
- 如果這個類的父類還沒有被初始化读宙,先初始化父類;
- 如果類中有初始化語句楔绞,系統(tǒng)依次執(zhí)行结闸。
初始化時(shí)機(jī):
創(chuàng)建類的實(shí)例唇兑,new
訪問/賦值 類或接口的靜態(tài)變量
調(diào)用類的靜態(tài)方法
反射(如Class,forName("com.demo.Test"))
初始化某個類的子類,父類也會被初始化
jvm啟動時(shí)被標(biāo)明為啟動類的類(Java Test)桦锄,java.exe
結(jié)束生命周期
- 執(zhí)行System.exit()
- 程序正常執(zhí)行結(jié)束
- 程序執(zhí)行過程中遇到異吃剑或錯誤而終止
- 操作系統(tǒng)出現(xiàn)錯誤導(dǎo)致jvm進(jìn)程終止
1.3類加載器
有三種類加載器
- 啟動類加載器:Bootstrap ClassLoader,不能被Java程序直接引用
- 擴(kuò)展類加載器:Extension ClassLoader察纯,開發(fā)者可以使用
- 應(yīng)用程序類加載器:Application ClassLoader帕棉,負(fù)責(zé)加載用戶類路徑指定的類,開發(fā)者可以直接使用
1.4類的加載
類的加載有三種模式
- 命令行啟動時(shí)由jvm初始化加載
- 通過Class.forName()動態(tài)加載
- 通過ClassLoader.loadClass()動態(tài)加載
Class.forName()和ClassLoader.loadClass()區(qū)別 |
---|
Class.forName():加載.class文件同事饼记,會對類進(jìn)行解釋香伴,執(zhí)行static塊 |
ClassLoader.loadClass():只將.class文件加載到j(luò)vm中 |
1.5 雙親委派模型
工作流程是:如果一個類加載器收到了類加載的請求,它首先不會自己去嘗試加載這個類具则,而是把請求委托給父加載器去完成即纲,依次向上,因此博肋,所有的類加載請求最終都應(yīng)該被傳遞到頂層的啟動類加載器中低斋,只有當(dāng)父加載器在它的搜索范圍中沒有找到所需的類時(shí),即無法完成該加載匪凡,子加載器才會嘗試自己去加載該類膊畴。