類或接口的解析
假設(shè)當(dāng)前代碼所處的類為D每界,如果要把一個從未解析過的符號引用N解析為一個類或接口C的直接引用誉裆,那虛擬機(jī)完成整個解析的過程需要以下3個步驟:
如果C不是一個數(shù)組類型永脓,那虛擬機(jī)將會把代表N的全限定名傳遞給D的類加載器去加載這個類C。在加載過程中间驮,由于元數(shù)據(jù)驗(yàn)證驾凶、字節(jié)碼驗(yàn)證的需要尘奏,又可能觸發(fā)其他相關(guān)類的加載動作滩褥,例如加載這個類的父類或?qū)崿F(xiàn)的接口。一旦這個加載過程出現(xiàn)了任何異常炫加,解析過程就宣告失敗瑰煎。
如果C是一個數(shù)組類型,并且數(shù)組的元素類型為對象俗孝,也就是N的描述符會是類似“[Ljava/lang/Integer”的形式酒甸,那將會按照第1點(diǎn)的規(guī)則加載數(shù)組元素類型。如果N的描述符如前面所假設(shè)的形式赋铝,需要加載的元素類型就是“java.lang.Integer”插勤,接著由虛擬機(jī)生成一個代表此數(shù)組維度和元素的數(shù)組對象。
如果上面的步驟沒有出現(xiàn)任何異常,那么C在虛擬機(jī)中實(shí)際上已經(jīng)成為一個有效的類或接口了农尖,但在解析完成之前還要進(jìn)行符號引用驗(yàn)證析恋,確認(rèn)D是否具備對C的訪問權(quán)限。如果發(fā)現(xiàn)不具備訪問權(quán)限卤橄,將拋出java.lang.IllegalAccessError異常绿满。
字段解析
要解析一個未被解析過的字段符號引用臂外,首先將會對字段表內(nèi)class_index項(xiàng)中索引的CONSTANT_Class_info符號引用進(jìn)行解析窟扑,也就是字段所屬的類或接口的符號引用。如果在解析這個類或接口符號引用的過程中出現(xiàn)了任何異常漏健,都會導(dǎo)致字段符號引用解析的失敗嚎货。如果解析成功完成,那將這個字段所屬的類或接口用C表示蔫浆,虛擬機(jī)規(guī)范要求按照如下步驟對C進(jìn)行后續(xù)字段的搜索殖属。
如果C本身就包含了簡單名稱和字段描述符都與目標(biāo)相匹配的字段,則返回這個字段的直接引用瓦盛,查找結(jié)束洗显。
否則,如果在C中實(shí)現(xiàn)了接口原环,將會按照繼承關(guān)系從下往上遞歸搜索各個接口和它的父接口挠唆,如果接口中包含了簡單名稱和字段描述符都與目標(biāo)相匹配的字段,則返回這個字段的直接引用嘱吗,查找結(jié)束玄组。
否則,如果C不是java.lang.Object的話谒麦,將會按照繼承關(guān)系從下往上遞歸搜索其父類俄讹,如果在父類中包含了簡單名稱和字段描述符都與目標(biāo)相匹配的字段,則返回這個字段的直接引用绕德,查找結(jié)束患膛。
否則,查找失敗耻蛇,拋出java.lang.NoSuchFieldError異常踪蹬。
如果查找過程成功返回了引用,將會對這個字段進(jìn)行權(quán)限驗(yàn)證城丧,如果發(fā)現(xiàn)不具備對字段的訪問權(quán)限延曙,將拋出java.lang.Ille-galAccessError異常。
類方法解析
類方法解析的第一個步驟與字段解析一樣亡哄,也需要先解析出類方法表的class_index項(xiàng)中索引的方法所屬的類或接口的符號引用枝缔,如果解析成功,我們依然用C表示這個類,接下來虛擬機(jī)將會按照如下步驟進(jìn)行后續(xù)的類方法搜索愿卸。
類方法和接口方法符號引用的常量類型定義是分開的灵临,如果在類方法表中發(fā)現(xiàn)class_index中索引的C是個接口,那就直接拋出java.lang.IncompatibleClassChangeError異常趴荸。
如果通過了第1步儒溉,在類C中查找是否有簡單名稱和描述符都與目標(biāo)相匹配的方法,如果有則返回這個方法的直接引用发钝,查找結(jié)束顿涣。
否則,在類C的父類中遞歸查找是否有簡單名稱和描述符都與目標(biāo)相匹配的方法酝豪,如果有則返回這個方法的直接引用涛碑,查找結(jié)束。
否則孵淘,在類C實(shí)現(xiàn)的接口列表及它們的父接口之中遞歸查找是否有簡單名稱和描述符都與目標(biāo)相匹配的方法蒲障,如果存在匹配的方法,說明類C是一個抽象類瘫证,這時查找結(jié)束揉阎,拋出java.lang.AbstractMethodError異常。
否則背捌,宣告方法查找失敗毙籽,拋出java.lang.NoSuchMeth-odError。
最后载萌,如果查找過程成功返回了直接引用惧财,將會對這個方法進(jìn)行權(quán)限驗(yàn)證,如果發(fā)現(xiàn)不具備對此方法的訪問權(quán)限扭仁,將拋出java.lang.IllegalAccessError異常垮衷。
接口方法解析
接口方法也需要先解析出接口方法表的class_index項(xiàng)中索引的方法所屬的類或接口的符號引用,如果解析成功乖坠,依然用C表示這個接口搀突,接下來虛擬機(jī)將會按照如下步驟進(jìn)行后續(xù)的接口方法搜索。
與類方法解析不同熊泵,如果在接口方法表中發(fā)現(xiàn)class_index中的索引C是個類而不是接口仰迁,那就直接拋出java.lang.Incom-patibleClassChangeError異常。
否則顽分,在接口C中查找是否有簡單名稱和描述符都與目標(biāo)相匹配的方法徐许,如果有則返回這個方法的直接引用,查找結(jié)束卒蘸。
否則雌隅,在接口C的父接口中遞歸查找翻默,直到j(luò)ava.lang.Object類(查找范圍會包括Object類)為止,看是否有簡單名稱和描述符都與目標(biāo)相匹配的方法恰起,如果有則返回這個方法的直接引用修械,查找結(jié)束。
否則检盼,宣告方法查找失敗肯污,拋出java.lang.NoSuchMeth-odError異常。