高分面試分析jvm如何實現(xiàn)多態(tài)
昨天就有一個小伙伴被一道面試題虐了,我也給了他一定深度的答案。但是我覺得不夠,我覺得應(yīng)該讓小伙伴們像我一樣,答題能答出驚喜感,于是就有了這篇文章。我會從Java層面到Hotshot源碼層面再到C++層面,完整分析這個問題。
這道面試題在好一些的互聯(lián)網(wǎng)公司,尤其是一二線,問到的概率非常大,建議小伙伴們把這篇文章吃透。

這樣說,六十分
多態(tài)是面向?qū)ο蟮娜筇匦灾唬覀€人認為,當(dāng)時設(shè)計OOP機制的時候,能夠想到多態(tài)的人,真特么太牛叉了。
多態(tài)理論第一次有了具體實現(xiàn)是在第一款面向?qū)ο蟮木幊陶Z言中,這個語言可能很多人沒聽過:smalltalk。此后出現(xiàn)的只要具備OOP機制的語言,都或多或少模仿或借鑒了前面語言的OOP實現(xiàn)機制。C++有沒有模仿或借鑒smalltalk,我不敢說,沒特別研究過smalltalk。但是我敢說,Java的多態(tài)是幾乎百分百模仿C++的多態(tài)實現(xiàn)的,不過做了一些細化。C++中只有直接調(diào)用、間接調(diào)用,而JVM通過不同的invoke指令來實現(xiàn)不同屬性的方法調(diào)用,這點后文會講到。
那什么是多態(tài)呢,滿足下面這幾個條件就可以稱為多態(tài):
1、繼承了某個類、實現(xiàn)了某個接口
2、重寫父類的方法、實現(xiàn)接口中的方法
3、父類引用指向子類對象

其實面試官問的這個問題,你這樣回答也算就著他這個問題做了回答。但是顯然,面試官想聽的不是這些,而是父類引用指向子類對象,進行方法調(diào)用,這個JVM底層是如何實現(xiàn)的。面試題就是為了篩人,所以面試的時候,能答多深就答多深,絕對加分。
順便說下,經(jīng)常跟多態(tài)聯(lián)系在一起的兩個詞:動態(tài)綁定、晚綁定。別到時面試官說這兩個詞,你一臉懵,那真的很掉分,面試官的臉色一下就暗淡灰沉下去了。當(dāng)面試官看到你的第一眼,心里給了你60分鐘時間來表現(xiàn),這下直接掉到5分鐘。更直接一點的,可能找個借口就走人了。
這樣說,七八十分
C++中的間接調(diào)用與直接調(diào)用,JVM抽象成了4個指令來完成:
1、invokevirtual:咱們平時寫代碼調(diào)用方法,最常用的就是這個指令。這個指令用于調(diào)用public、protected修飾,且不被static、final修飾的方法。跟多態(tài)機制有關(guān)。
2、invokeinterface:跟invokevirtual差不多。區(qū)別是多態(tài)調(diào)用時,如果父類引用是對象,就用invokevirtual。如果父類引用是接口,就用這個。
3、invokespecial:只用于調(diào)用私有方法,構(gòu)造方法。跟多態(tài)機制無關(guān)。
4、invokestatic:只用于調(diào)用靜態(tài)方法。與多態(tài)機制無關(guān)。
跟面試官當(dāng)然要扯點高逼格的對吧,那咱們就講講invokeinterface。這個指令為什么逼格高呢?因為它的底層實現(xiàn)比其他幾個指令都要復(fù)雜,如圖

其他的invoke指令的后面就是2個字節(jié)的操作數(shù),拿著操作數(shù)去常量池中就可以找到類信息、方法信息。但是invokeinterface你會發(fā)現(xiàn),它后面操作數(shù)占了4個字節(jié),這4個字節(jié)還不全是常量池索引,一起看下這個指令的結(jié)構(gòu),上圖:

這個指令格式我解釋一下:
1、第二個字節(jié)跟第三個字節(jié)合起來是常量池的索引,對應(yīng)常量池項JVM_CONSTANT_InterfaceMethodref,這里面包含接口的元信息、方法信息。
2、第四個字節(jié)是這個方法的參數(shù)個數(shù)。是不是有小伙伴覺得很奇怪,show方法沒有參數(shù)呀,這邊怎么是1,是JVM的bug?呵,如果JVM有這么低級的bug,JVM也不會有今天的地位了。非靜態(tài)方法就算沒有參數(shù),也默認有一個,就是this指針。
其實這個參數(shù)個數(shù)完全沒必要記錄,可以通過解析方法的簽名計算出來,不明白當(dāng)時為什么做這樣的設(shè)計。面試的時候這點記得說,很加分。其實字節(jié)碼文件中有很多可以優(yōu)化的點,后面準備共享這方面的面試題,沒人想打我吧。^_^

3、第五個字節(jié)永遠為0,歷史原因遺留。我查了一些資料,得到的答案是:為額外的運算元預(yù)留空間。子牙老師表示這個字我都認識,但是它組合在一起表達的意思我真不懂,是不是我太菜了。哎,還是太菜了。
有些小伙伴可能就想:答到這個份上才七八十分?那后面還能怎么說哦。咱們現(xiàn)在才只說到invokeinterface指令,那這個指令是怎么找到要調(diào)用的方法的呢?JVM的虛表機制到底是什么樣的呢?又是怎么與C++的虛表機制合二為一的呢?虛表分發(fā)機制又是怎樣的呢?這些才是這個問題的精髓。
這點就留到下篇文章寫吧。文章太長,讀起來也疲憊。
傳送門 高分面試從Hotspot源碼層面剖析java多態(tài)實現(xiàn)原理
以上就是高分面試分析jvm如何實現(xiàn)多態(tài)的詳細內(nèi)容,更多關(guān)于jvm實現(xiàn)多態(tài)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java 基礎(chǔ)之JavaBean屬性命名規(guī)范問題
這篇文章主要介紹了java 基礎(chǔ)之JavaBean屬性命名規(guī)范問題的相關(guān)資料,需要的朋友可以參考下2017-05-05
JAVA 統(tǒng)計字符串中中文,英文,數(shù)字,空格,特殊字符的個數(shù)
這篇文章主要介紹了JAVA 統(tǒng)計字符串中中文,英文,數(shù)字,空格,特殊字符的個數(shù) ,本文通過一段代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-06-06
Spring配置shiro時自定義Realm中屬性無法使用注解注入的解決辦法
今天小編就為大家分享一篇關(guān)于Spring配置shiro時自定義Realm中屬性無法使用注解注入的解決辦法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
springboot項目mapper無法自動裝配未找到?UserMapper?類型的Bean解決辦法
這篇文章給大家介紹了springboot項目mapper無法自動裝配,未找到?‘userMapper‘?類型的?Bean解決辦法(含報錯原因),文章通過圖文結(jié)合的方式介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下2024-02-02
json如何解析混合數(shù)組對象到實體類的list集合里去
這篇文章主要介紹了json解析混合數(shù)組對象到實體類的list集合里去的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
JDK都出到14了,你有什么理由不會函數(shù)式編程(推薦)
這篇文章主要介紹了JDK都出到14了,你有什么理由不會函數(shù)式編程,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
java數(shù)據(jù)結(jié)構(gòu)-堆實現(xiàn)優(yōu)先隊列
通常都把隊列比喻成排隊買東西,大家都很守秩序,先排隊的人就先買東西。但是優(yōu)先隊列有所不同,它不遵循先進先出的規(guī)則,而是根據(jù)隊列中元素的優(yōu)先權(quán),優(yōu)先權(quán)最大的先被取出,這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)-堆實現(xiàn)優(yōu)先隊列,感興趣的朋友一起看看吧2021-08-08

