Java的動(dòng)態(tài)綁定分析

從下面的例子開始:

package dog.test;

//被調(diào)用的父類
public class Dog {

    public void bark() {
        System.out.println("Woof!");

    }
}
package dog.test;

public class ShepherdDog extends Dog {

    @Override
    public void bark() { 
        System.out.println("Woof!Woof!Woof!");

    }
}
import dog.test.*;
public class AutoCall{

    public static void main(String[] args){
        //多態(tài)
        Dog dog = new ShepherdDog(); 
        //打印結(jié)果: Woof!Woof!Woof!
        dog.bark(); 

     }
}

了解 Java 語(yǔ)法的都知道這段程序會(huì)輸出:

Woof!Woof!Woof!

原因是 Java 中的多態(tài),bark() 方法已經(jīng)被子類覆寫(override)過(guò)刽严,所以程序調(diào)用的是子類的 bark() 食磕。

那 JVM 是怎么知道 dog.bark() 調(diào)用的是子類的方法而非父類的呢第美?

首先先介紹一下 JVM 管理的一個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu)——方法表虎韵。

在JVM加載類文件時(shí)雁佳,會(huì)在運(yùn)行時(shí)數(shù)據(jù)區(qū)里存放一些與該類有關(guān)的信息涨享,運(yùn)行時(shí)數(shù)據(jù)區(qū)由方法區(qū)筋搏、堆區(qū)棧區(qū)厕隧、程序計(jì)數(shù)器等組成奔脐。方法表就存放在方法區(qū)中。

方法表以數(shù)組的形式記錄了當(dāng)前類和其所有超類的可見方法字節(jié)碼在內(nèi)存中的直接地址吁讨。

方法表有兩個(gè)特點(diǎn):

  • 子類方法表繼承父類的方法髓迎;
  • 相同的方法(相同方法簽名:方法名和參數(shù)列表)在所有類的方法表中的索引相同。

多態(tài)調(diào)用的字節(jié)碼指令代碼

0  new dog.test.ShepherdDog [13] //在堆中開辟一個(gè) ShepherdDog 對(duì)象的內(nèi)存空間建丧,并將對(duì)象引用壓入操作數(shù)棧
3  dup  
4  invokespecial #7 [15] // 調(diào)用初始化方法來(lái)初始化堆中的 ShepherdDog 對(duì)象 
7  astore_1 //彈出操作數(shù)棧的 ShepherdDog 對(duì)象引用壓入局部變量1中
8  aload_1 //取出局部變量1中的對(duì)象引用壓入操作數(shù)棧
9  invokevirtual #15 //調(diào)用 bark() 方法
12  return
  1. invokevirtual 指令中的#15指的是 AutoCall 類的常量池中第15個(gè)常量表的索引項(xiàng)竖般。這個(gè)常量表(CONSTATN_Methodref_info ) 記錄的是方法 bark() 信息的符號(hào)引用(包括 bark() 在的類名,方法名和返回類型)茶鹃。 JVM 會(huì)首先根據(jù)這個(gè)符號(hào)引用找到調(diào)用方法 bark 的類的全限定名: dog.test.Dog 涣雕。這是因?yàn)檎{(diào)用方法 bark() 的類的對(duì)象 dog 聲明為 Dog 類型。

  2. 在 Dog 類型的方法表中查找方法 bark() 闭翩,如果找到挣郭,則將方法 bark 在方法表中的索引項(xiàng)11(如上圖)記錄到 AutoCall 類的常量池中第15個(gè)常量表中(常量池解析 )。這里有一點(diǎn)要注意:如果 Dog 類型方法表中沒有方法 bark 疗韵,那么即使 ShepherdDog 類型中方法表有兑障,編譯的時(shí)候也通過(guò)不了。因?yàn)檎{(diào)用方法 bark() 的類的對(duì)象 dog 的聲明為 Dog 類型蕉汪。

  3. 在調(diào)用 invokevirtual 指令前有一個(gè) aload_1 指令流译,它會(huì)將開始創(chuàng)建在堆中的 ShepherdDog 對(duì)象的引用壓入操作數(shù)棧。然后invokevirtual指令會(huì)根據(jù)這個(gè) ShepherdDog 對(duì)象的引用首先找到堆中的 ShepherdDog 對(duì)象者疤,然后進(jìn)一步找到 ShepherdDog 對(duì)象所屬類型的方法表福澡。

  4. 這是通過(guò)第(2)步中解析完成的#15常量表中的方法表的索引項(xiàng)11,可以定位到 ShepherdDog 類型方法表中的方法 bark()驹马,然后通過(guò)直接地址找到該方法字節(jié)碼所在的內(nèi)存空間革砸。

那么我們發(fā)現(xiàn)除秀,僅僅根據(jù)對(duì)象 dog 和聲明類型 Dog 并不能確定調(diào)用方法 dark() 的位置,必須根據(jù) dog 在堆中實(shí)際創(chuàng)建的對(duì)象 ShepherdDog 來(lái)確定 dark() 所在的位置算利。

這種在程序運(yùn)行中册踩,通過(guò)動(dòng)態(tài)創(chuàng)建對(duì)象來(lái)定位方法的方式,就叫做動(dòng)態(tài)綁定機(jī)制效拭。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末暂吉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缎患,更是在濱河造成了極大的恐慌慕的,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件较锡,死亡現(xiàn)場(chǎng)離奇詭異业稼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)蚂蕴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門低散,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人骡楼,你說(shuō)我怎么就攤上這事熔号。” “怎么了鸟整?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵引镊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我篮条,道長(zhǎng)弟头,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任涉茧,我火速辦了婚禮赴恨,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘伴栓。我一直安慰自己伦连,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布钳垮。 她就那樣靜靜地躺著惑淳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饺窿。 梳的紋絲不亂的頭發(fā)上歧焦,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音短荐,去河邊找鬼倚舀。 笑死叹哭,一個(gè)胖子當(dāng)著我的面吹牛忍宋,可吹牛的內(nèi)容都是我干的痕貌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼糠排,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼舵稠!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起入宦,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤哺徊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后乾闰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體落追,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年涯肩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了轿钠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡病苗,死狀恐怖疗垛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情硫朦,我是刑警寧澤贷腕,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站咬展,受9級(jí)特大地震影響泽裳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜破婆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一涮总、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荠割,春花似錦妹卿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至嚎朽,卻和暖如春铺纽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哟忍。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工狡门, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陷寝,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓其馏,卻偏偏與公主長(zhǎng)得像凤跑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叛复,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354