每天進(jìn)步一點點!
在前面的幾篇中互站,我們已經(jīng)詳細(xì)學(xué)習(xí)了Class字節(jié)碼文件的結(jié)構(gòu)私蕾,包含哪些內(nèi)容已經(jīng)內(nèi)容的含義,下面幾篇我們將研習(xí)一下類的加載胡桃。
虛擬機的類加載機制: 虛擬機把描述類的數(shù)據(jù)從Class文件加載到內(nèi)存踩叭,并對數(shù)據(jù)進(jìn)行校驗,轉(zhuǎn)換解析和初始化翠胰,最終形成可以被虛擬機直接使用的Java類型容贝。
整個生命周期包括:加載(Loading)、驗證(Verification)之景、準(zhǔn)備(Preparation)斤富、解析(Resolution)、初始化(Initialization)锻狗、使用(Using) 和 卸載(Unloading)七個階段满力。
其中焕参,加載、驗證油额、準(zhǔn)備龟糕、初始化和卸載這5個階段的順序是確定的。
加載到內(nèi)存中的類都包含哪些信息我們在前面已經(jīng)學(xué)習(xí)過了悔耘,大家還記得嗎?包括魔數(shù)我擂,java版本衬以,常量池,類的訪問標(biāo)識校摩,類名看峻,父類名,接口信息衙吩,字段互妓,方法和屬性等。
而對于虛擬機來說坤塞,類又是可以在運行期動態(tài)加載冯勉,動態(tài)連接(驗證,準(zhǔn)備摹芙,解析三個部分統(tǒng)稱為連接)的灼狰。
解析階段則不一定:因為java支持運行時綁定(也叫動態(tài)綁定或晚期綁定,綁定:就是將一個方法的調(diào)用與方法所在的類關(guān)聯(lián)起來)浮禾。
什么是動態(tài)綁定交胚?在程序執(zhí)行期間根據(jù)對象的類型進(jìn)行綁定,這也是java的默認(rèn)綁定方式盈电,幾乎所有的方法都是后期綁定蝴簇。
那么,動態(tài)的綁定的意義是什么呢匆帚?簡單是為了實現(xiàn)多態(tài)熬词,比如當(dāng)方法中參數(shù)是父類或者接口的時候。
與之相對應(yīng)的還有一個概念動態(tài)綁定(前期綁定)吸重,也就是在程序執(zhí)行前(編譯期間)進(jìn)行綁定荡澎,final,static晤锹,private和構(gòu)造方法都是前期綁定摩幔。
下面我們來看看來加載的具體過程。
加載:虛擬機對加載的開始時間沒有強制約束鞭铆。
初始化:以下5種情況有可能進(jìn)行初始化操作或衡。
1. 當(dāng)虛擬機執(zhí)行new焦影、getstatic、putstatic和invokestatic這四條字節(jié)碼指令的時候封断,虛擬機會先查詢該類是否已經(jīng)初始化過斯辰,如果沒有,則需要先將該類進(jìn)行初始化坡疼。比較常見的場景:
使用new關(guān)鍵字實例化對象的時候彬呻;
讀取或設(shè)置一個類的靜態(tài)字段(被final修飾,已在編譯器把結(jié)果放入常量池的靜態(tài)字段除外)的時候柄瑰;
調(diào)用一個類的靜態(tài)方法的時候闸氮。
2. 使用java.lang.reflect包的方法對類進(jìn)行反射調(diào)用的時候,如果類沒有進(jìn)行過初始化教沾,則需要先觸發(fā)其初始化蒲跨。
3. 當(dāng)初始化一個類的時候,如果發(fā)現(xiàn)其父類還沒有進(jìn)行過初始化授翻,則需要先觸發(fā)其父類的初始化或悲。
4. 當(dāng)虛擬機啟動時,用戶需要指定一個要執(zhí)行的主類(包含main()方法的那個類)堪唐,虛擬機會先初始化這個主類巡语。
5.
當(dāng)使用jdk1.7動態(tài)語言支持時,如果一個java.lang.invoke.MethodHandle實例最后的解析結(jié)果REF_getstatic淮菠,REF_putstatic捌臊,REF_invokeStatic的方法句柄,并且這個方法句柄所對應(yīng)的類沒有進(jìn)行初始化兜材,則需要先出觸發(fā)其初始化理澎。
喜歡文章或想一起學(xué)習(xí)的朋友可以關(guān)注我,給我點贊曙寡,我將會持續(xù)更新糠爬,有什么疑問或文中有不當(dāng)之處請給我留言,真誠地希望能與大家一起交流探討举庶,學(xué)習(xí)進(jìn)步执隧。