字節(jié)碼執(zhí)行引擎

運行時棧幀結(jié)構(gòu)

  • 棧幀是虛擬機棧中的元素,每一個方法的調(diào)用對應(yīng)著一個棧幀的入棧出棧豁生。棧幀包括局部變量表、操作數(shù)棧漫贞、動態(tài)鏈接甸箱、方法返回地址等信息。
  • 在編譯階段绕辖,棧幀中需要多大的局部變量表和多深的操作數(shù)棧都是已經(jīng)確定的摇肌,并且寫入到方法表的Code屬性中。

局部變量表

  • 編譯期間仪际,就在方法的Code屬性的max_locals數(shù)據(jù)項中確定了該方法所需要分配的局部變量表的最大容量
  • 局部變量表已slot為最小單位,一個slot32位昵骤。long和double占兩個(不存在線程問題)树碱。第0個slot存放this,從1開始按照變量順序和作用域分配slot变秦。
  • 類變量在準備和初始化階段會復(fù)制好成榜,局部變量沒有這個東西,必須手工復(fù)制才能使用蹦玫。

操作數(shù)棧

  • 和局部變量表一樣赎婚,操作數(shù)棧的最大深度在編譯時寫入到了Code屬性的max_stacks中刘绣。32位1個容量,64位2個容量挣输。
  • Java虛擬機的解釋執(zhí)行引擎稱為“基于棧的執(zhí)行引擎”纬凤,就是指這個。

動態(tài)鏈接

  • 每個棧幀都包含一個指向運行時常量池中該棧幀所屬方法的引用撩嚼,持有該引用是為了支持方法調(diào)用過程中的動態(tài)連接停士。

方法返回地址

  1. 執(zhí)行引擎遇到任意一個方法返回的字節(jié)碼指令,也就是所謂的正常完成出口完丽。
  2. 在方法執(zhí)行的過程中遇到了異常恋技,并且這個異常沒有在方法內(nèi)進行處理,也就是只要在本方法的異常表中沒有搜索到匹配的異常處理器逻族,就會導(dǎo)致方法退出蜻底,這種方式成為異常完成出口。
  • 無論通過哪種方式退出聘鳞,在方法退出后都返回到該方法被調(diào)用的位置薄辅,方法正常退出時,調(diào)用者的pc計數(shù)器的值作為返回地址搁痛,而通過異常退出的长搀,返回地址是要通過異常處理器表來確定,棧幀中一般不會保存這部分信息鸡典。本質(zhì)上源请,方法的退出就是當(dāng)前棧幀出棧的過程。

方法調(diào)用

  • 不是方法執(zhí)行彻况,而是確定被調(diào)用方法的版本(哪個方法)谁尸,不涉及運行。因為Class文件中存放的是符號引用纽甘,不是直接引用良蛮。
    有兩種調(diào)用方式
  1. 解析調(diào)用:在編譯器就確定目標方法。
  2. 分派調(diào)用:重載悍赢、重寫决瞳。

解析

類加載的解析階段,會將一部分符號引用轉(zhuǎn)化為直接引用左权,前提是:方法在程序運行之前就有一個可確定的調(diào)用版本皮胡,并且運行期不可變。

  • 主要包括靜態(tài)方法和私有方法赏迟。
  • 解析調(diào)用是靜態(tài)的過程屡贺,在編譯期間就完全確定,在類加載的解析階段就會把符號引用轉(zhuǎn)化為直接引用。

分派

靜態(tài)分派:依賴靜態(tài)類型類確定方法執(zhí)行版本甩栈。典型應(yīng)用:重載泻仙。
解析和分派不是排他的,靜態(tài)分派會在類加載器就進行解析量没,而靜態(tài)方法的重載玉转,也是通過靜態(tài)分派確定重載版本的。

public class StaticDispatch {
    static abstract class Human{
    }
    
    static class Man extends Human{
    }
    
    static class Woman extends Human{
    }
    public void sayHello(Human human) {
        System.out.println("hello human");
    }
    public void sayHello(Man man) {
        System.out.println("hello man");
    }
    public void sayHello(Woman woman) {
        System.out.println("hello woman");
    }
    
    public static void main(String[] args) {
        Human man = new Man();
        Human woman = new Woman();
        StaticDispatch sd = new StaticDispatch();
        sd.sayHello(man);
        sd.sayHello(woman);
    }
}
output:
都輸出hello human

Human man = new Man();
Human 是變量的靜態(tài)類型允蜈,編譯期可知的冤吨。
Man是變量的實際類型,運行期才確定饶套。

動態(tài)分派:運行期根據(jù)實際類型確定方法的執(zhí)行版本漩蟆。典型應(yīng)用:重寫。

public class DynamicDispatch {
    static abstract class Human{
        protected abstract void sayHello();
    }
    static class Man extends Human{
        public void sayHello() {
            System.out.println("hello man");
        }
    }
    static class Woman extends Human{
        public void sayHello() {
            System.out.println("hello woman");
        }
    }
    public static void main(String[] args) {
        Human man = new Man();
        Human woman = new Woman();
        man.sayHello();
        woman.sayHello();
    }
}

output:
hello man
hello woman

*虛擬機如何實現(xiàn)動態(tài)分派妓蛮?
  因為動態(tài)分派是非常頻繁的動作怠李,而且選擇方法版本時需要運行時在類的方法元數(shù)據(jù)中搜索合適的目標方法,所以基于性能蛤克,虛擬機為類在方法區(qū)中建立了一個虛方法表捺癞。使用虛方法表索引來代替元數(shù)據(jù)以提高性能。
  虛方法中存放著各個方法的實際入口地址构挤,如果子類沒有重寫父類的方法髓介,那么就存放著父類方法的入口地址;如果重寫了筋现,就存放子類實現(xiàn)方法的入口地址唐础。

基于棧的指令集和基于寄存器的指令集

基于棧:可移植,速度慢矾飞。
基于寄存器:速度快一膨。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市洒沦,隨后出現(xiàn)的幾起案子豹绪,更是在濱河造成了極大的恐慌,老刑警劉巖申眼,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞒津,死亡現(xiàn)場離奇詭異,居然都是意外死亡括尸,警方通過查閱死者的電腦和手機仲智,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姻氨,“玉大人,你說我怎么就攤上這事剪验‰群福” “怎么了前联?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長娶眷。 經(jīng)常有香客問我似嗤,道長,這世上最難降的妖魔是什么届宠? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任烁落,我火速辦了婚禮,結(jié)果婚禮上豌注,老公的妹妹穿的比我還像新娘伤塌。我一直安慰自己,他們只是感情好轧铁,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布每聪。 她就那樣靜靜地躺著,像睡著了一般齿风。 火紅的嫁衣襯著肌膚如雪药薯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天救斑,我揣著相機與錄音童本,去河邊找鬼。 笑死脸候,一個胖子當(dāng)著我的面吹牛穷娱,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纪他,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼鄙煤,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了茶袒?” 一聲冷哼從身側(cè)響起梯刚,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎薪寓,沒想到半個月后亡资,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡向叉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年锥腻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片母谎。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡瘦黑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情幸斥,我是刑警寧澤匹摇,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站甲葬,受9級特大地震影響廊勃,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜经窖,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一坡垫、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧画侣,春花似錦冰悠、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宪卿,卻和暖如春的诵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背佑钾。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工西疤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人休溶。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓代赁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親兽掰。 傳聞我的和親對象是個殘疾皇子芭碍,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容