主要講述:
1. .class文件如何加載到內(nèi)存
2. 加載到內(nèi)存之后做了什么览效。
首先是概念为严,什么是類加載機(jī)制?
將類的數(shù)據(jù)從Class文件加載到內(nèi)存垛膝,并對數(shù)據(jù)進(jìn)行校驗(yàn)鳍侣、轉(zhuǎn)換解析和初始化丁稀,最終形成可以被JAVA虛擬機(jī)使用的類型。
一倚聚、類的加載時(shí)機(jī)
類的生命周期分為:
1.加載階段线衫,注意區(qū)分類的加載機(jī)制,和加載階段惑折,加載階段授账,只是讀入 .Class 二進(jìn)制流進(jìn)內(nèi)存。
2.鏈接惨驶,又分為矗积,驗(yàn)證,準(zhǔn)備敞咧,解析棘捣。
3.初始化
4.使用
5.卸載
*** 什么時(shí)候去加載一個(gè)類?
加載階段是任意的休建。
初始化階段有嚴(yán)格的限制乍恐,有且只有以下5種情況,必須立即進(jìn)行初始化:
1.new 一個(gè)對象测砂,調(diào)用類的靜態(tài)方法茵烈,使用類的靜態(tài)變量(final修飾的不算,在編譯階段已經(jīng)放到常量區(qū)了)
2.反射一個(gè)對象
3.初始化一個(gè)類的時(shí)候砌些,發(fā)現(xiàn)其父類沒有初始化呜投,先初始化這個(gè)父類。
4.虛擬機(jī)啟動的時(shí)候存璃,執(zhí)行main函數(shù)的那個(gè)主類仑荐。
5. JDK 1.7動態(tài)語言支持。
接口類有不同:
接口類初始化的時(shí)候纵东,不回去初始化接口類的父類粘招。
各個(gè)過程描述
1.加載階段
包括三件事:
a.以全限定名字得到類的二進(jìn)制字節(jié)流。
b.將這個(gè)字節(jié)流所代表的靜態(tài)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)偎球。
c.在內(nèi)存中生成類的Class對象洒扎。
注意,一個(gè)加載器和一個(gè)類衰絮,唯一確定了JVM中的一個(gè)類袍冷。
2.驗(yàn)證
就是各種驗(yàn)證
3.準(zhǔn)備
為類變量分配內(nèi)存并設(shè)置初始值。注意這個(gè)初始值與類無關(guān)(int 的值都賦成0)猫牡。與類相關(guān)的階段叫做 初始化 胡诗。
4.解析
就是各種解析。
5.初始化
初始化階段,開始執(zhí)行Java代碼乃戈。
初始化階段褂痰,其實(shí)就是執(zhí)行 <clinit> 方法的過程亩进。
<clinit>方法症虑,里面含有,所有類變量的賦值動作和靜態(tài)語句塊中的語句归薛。前面這兩種操作的優(yōu)先級相同谍憔,各個(gè)操作按順序執(zhí)行。
<clinit>方法保證主籍,在子類<clinit>方法執(zhí)行之前习贫,父類的<clinit>執(zhí)行完畢。
接口可能沒有<clinit>方法千元,接口不能使用靜態(tài)塊苫昌,接口可以使用靜態(tài)賦值。
*重點(diǎn)*幸海,虛擬機(jī)會保證一個(gè)類的 <clinit>方法只會被一個(gè)線程執(zhí)行祟身。所以 static 變量的復(fù)制初始化等操作,都是安全的(static Test test = new Test())物独。
類加載器
加載這個(gè)類的類加載器和這個(gè)類袜硫,兩個(gè)確定了一個(gè)類在JVM中的唯一性。
這里說的相等挡篓,指的是婉陷,equals、instanceof等方法官研。
類加載器的種類:
1.從虛擬機(jī)的角度來看秽澳,只有兩種,一種是啟動類加載器(bootstrap classloader)戏羽,虛擬機(jī)的一部分肝集,用c++寫。2.其他的加載器蛛壳,用java寫杏瞻。
系統(tǒng)提供了三種加載器:
1.啟動類加載器
2.擴(kuò)展類加載器
3.應(yīng)用程序加載器(一般程序默認(rèn)使用)
雙親委派模型:
要求每個(gè)加載器都要有一個(gè)父類。
工作過程:
每次加載器收到一個(gè)加載請求衙荐,會先交給父類捞挥,看父類能不能加載。會一直上傳到頂層忧吟。