klass模型
地球人都知道jvm底層是c++實現(xiàn)的,c++同樣是面向?qū)ο蟮乃鹎晕覀兩蠈拥膉ava對象必然會對應(yīng)著底層的一個c++對象,顯而易見顾翼,這個klass就是c++中對象的表現(xiàn)形式台腥,接下來我們先來看看klass模型類的繼承結(jié)構(gòu)宏赘。
instanceKlass
對應(yīng)的普通的java類
接下來說一下它的三個子類
1、InstanceMirrorKlass
用來表示java.lang.Class,是jvm暴露給程序使用的黎侈,也就是說我們代碼中使用的對象就是這個實例察署,它是存儲在堆區(qū)的,而jvm內(nèi)部使用的是instanceKlass峻汉,它是存儲在方法區(qū)也就是元空間贴汪。(注:這里解釋一下,方法區(qū)是jvm的規(guī)范休吠,元空間是HotSpot的具體實現(xiàn))
2扳埂、InstanceRefKlass
用來表示java.lang.ref.Reference類
3、InstanceClassLoaderKlass
用來遍歷某個加載器加載的類
ArrayKlass
表示數(shù)組的元信息
1瘤礁、TypeArrayKlass
基本數(shù)據(jù)類型數(shù)組
2阳懂、ObjArrayKlass
引用數(shù)據(jù)類型數(shù)組
類的加載過程
類的生命周期是由7個階段組成,但是類的加載是說的前五個階段柜思,看下圖所示
加載
過程
1岩调、通過類的全限定名獲取存儲該類的class文件
2、解析成運行時數(shù)據(jù)酝蜒,即instanceKlass實例誊辉,存放在方法區(qū)
3、在堆區(qū)生成該類的Class對象亡脑,即InstanceMirrorKlass實例
時機
1堕澄、創(chuàng)建類的實例的時候
2、訪問某個類或接口的靜態(tài)變量霉咨,或者給該靜態(tài)變量賦值
3蛙紫、調(diào)用類的靜態(tài)方法
4、通過反射執(zhí)行上述三種行為
5途戒、初始化子類時會觸發(fā)父類的初始化
6坑傅、 Java虛擬機啟動時被標明為啟動類的類(有main方法的類)
7、JDK1.7開始提供的動態(tài)語言支持(了解即可)
預(yù)加載
包裝類喷斋、String唁毒、Thread
驗證
1、文件格式驗證
2星爪、元數(shù)據(jù)驗證
3浆西、字節(jié)碼驗證
4、符號運用驗證
準備
為靜態(tài)變量分配內(nèi)存顽腾、賦初值近零。
如下圖各種數(shù)據(jù)的初始值
如果是被final修飾,在編譯的時候會給屬性添加ConstantValue屬性,準備階段直接完成賦值久信,即沒有賦初值這一步窖杀。
解析
將常量池中的符號引用轉(zhuǎn)為直接引用
解析后的信息存儲在ConstantPoolCache類實例中
1、類或接口的解析
2裙士、字段解析
3入客、方法解析
4、接口方法解析
初始化
執(zhí)行靜態(tài)代碼塊潮售,完成靜態(tài)變量的賦值
方法中語句的先后順序與代碼的編寫順序有關(guān)
類加載細節(jié)
子類訪問父類的靜態(tài)字段有兩種實現(xiàn)方式
1痊项、先去子類的鏡像類中去取锅风,如果有直接返回酥诽,如果沒有,會沿著集成鏈將請求往上拋皱埠,很明顯這種算法的性能隨繼承鏈的deep而上升肮帐,算法復(fù)雜度為O(n)
2、借助另外的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)边器,使用K-V的格式 存儲训枢,查詢性能為O(1)。HotSpot就是使用的第二種方式忘巧,借助另外的數(shù)據(jù)結(jié)構(gòu)ConstantPoolCache,常量池類ConstantPool中有個屬性_cache指向了這個結(jié)構(gòu)恒界。每一條數(shù)據(jù)對應(yīng)一個類ContantPoolCacheEntry.
ConstantPool/ConstantPoolCache
每個InstanceKlass關(guān)聯(lián)著一個ConstantPool,作為該類型的運行時常量池砚嘴。這個常量池的結(jié)構(gòu)跟Class文件里的常量池基本上是對應(yīng)的
ConstantPoolCache主要用于存儲某些字節(jié)碼指令所需的解析(resolve)好的常量項十酣,例如給[get|put]static、[get|put]field际长、invoke[static|special|virtual|interface|dynamic]等指令對應(yīng)的常量池項用