一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - JVM 方法調用之動態分派(詳解)

JVM 方法調用之動態分派(詳解)

2020-09-22 10:05Java教程網 Java教程

下面小編就為大家帶來一篇JVM 方法調用之動態分派(詳解)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

1. 動態分派

一個體現是重寫(override)。下面的代碼,運行結果很明顯。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class App {
 
 public static void main(String[] args) {
  Super object = new Sub();
  object.f();
 }
}
 
 class Super {
 public void f() {
  System.out.println("super : f()");
 }
 
 public void f(int i) {
  System.out.println("super : f(int)");
 }
}
 
class Sub extends Super{
 
 @Override
 public void f() {
  System.out.println("sub : f()");
 }
 
 @Override
 public void f(int i) {
  System.out.println("sub : f(int)");
 }
 
 public void f(char c) {
  System.out.println("sub : f(char)");
 }
}

最終輸出sub : f();

那么虛擬機是怎么做到動態分派的呢?

不同的虛擬機有不同的實現,最常用的是使用虛方法表(Virtual Method Table)

2. 虛方法表

對于Super和Sub類,虛方法表大致如下:(靈魂畫師)

JVM 方法調用之動態分派(詳解)

上面的靈魂畫作是什么意思呢?

虛方法表中存放著各個方法的實際入口地址。如果某個方法在子類中沒有被重寫,那子類的虛方法表里面的地址入口和父類相同簽名的方法的地址入口是一致的,都指向父類的實現入口。如果子類中重寫了這個方法,子類方法表中的地址將會替換為向子類實現版本的入口地址。

從上圖主要得出幾個信息:

a. 上圖的大部分方法,子類Super和Sub均沒有重寫,那么都指向父類Object的類型數據。f()和f(int)方法,父類子類都實現了,那么兩者就指向不同的實現地址。f(char)只在子類定義實現,自然指向子類的類型數據。

b. 為了程序實現上的方便,具有相同簽名的方法,在父類,子類的虛方法表中都應當具有一樣的索引序號,這樣當類型變換時,僅需要變更查找的方法表,就可以從不同的虛方法表中按索引轉換出所需要的入口地址。

3. 實例分析

以本文開頭的代碼進行分析。通過javap命令查看main方法的指令。

JVM 方法調用之動態分派(詳解)

其中的invokevirtual指令詳細調用過程是這樣的:

1)指令中的#19指的是App類的常量池中第19個常量表的索引項。這個常量表(CONSTATN_Methodref_info)記錄的是方法f()信息的符號引用,JVM首先根據這個符號引用找到調用方法f()的類的全限定名com.khlin.Super,這是因為變量object被聲明為Super類型。

2) 在Super類型的方法表中查找方法f(),如果找到,則將方法f()在方法表中的索引項(具體值我不了解,這里將其記為index) 記錄到App類的常量池中第19個常量表中(常量池解析)。因此,如果Super類型方法表中沒有f(),那么即使Sub類型的方法表有該方法,也會報編譯失敗。

3)在調用invokevirtual指令前有一個aload_1指令,它會將開始創建中堆中的Sub對象的引用壓入操作數棧。然后invokevirtual指令會根據這個Sub對象的引用首先找到堆中的Sub對象,然后進一步找到Sub對象所屬類型的方法表。

4)這時,通過2)查找的index,可以定位到Sub類型方法表中的f()方法,然后通過直接地址找到該方法字節碼所在的內存空間。這就是父類和子類相同簽名的方法索引序號一致的用處。

4. 綜合考慮:一個可能想錯的例子

將本文開頭的代碼里的main方法稍作修改,調用其他的方法。

?
1
2
3
4
5
public static void main(String[] args) {
   Super object = new Sub();
   char c = 'a';
   object.f(c);
  }

結果將輸出sub : f(int)

明明Sub方法里有完全一樣類型的f(char)方法,卻調用的是f(int).

相信通過前面的學習,已經可以明白原因了。

在object.f(c)調用時,虛擬機先到Super類的方法表里,查找最為合適的方法。

Super類里沒有剛好參數為char的f(char)方法,按照前面靜態分派和參數類型自動轉換的學習,可以知道,編譯器使用了除了f(char)之外最為合適的方法f(int)。獲取到索引后,通過索引到實際對象的Sub方法表里找到f(int)方法,最終執行的就是Sub類的f(int)方法。

該方法的字節碼指令證明了上述的論證。

JVM 方法調用之動態分派(詳解)

以上這篇JVM 方法調用之動態分派(詳解)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲高清国产品国语在线观看 | 被黑人同学彻底征服全文小说阅读 | 1024视频色版在线网站 | www.爱操 | 日日爱669| 亚洲国产视频网站 | 国产精品色爱综合网 | 美女脱一净二净不带胸罩 | 色综合久久综合网欧美综合网 | 高清男的插曲女的 欢迎你老狼 | 国产精品露脸国语对白手机视频 | 欧美8x8x| 亚洲高清免费在线观看 | 国产一区二区三区在线看 | 美女被躁了在线观看视频 | 美女舒服好紧太爽了视频 | 视频在线视频免费观看 | 农村妇女野外性生话免费视频 | 极品丝袜老师h系列全文阅读 | 色婷亚洲| 古代翁熄系小说辣文 | 91啦在线播放 | 国产91精品在线观看 | 51国产午夜精品免费视频 | 很黄的网站在线观看 | 2021国产麻豆剧传媒剧情动漫 | 三级全黄裸体 | 美女奶口隐私免费视频网站 | 色依依视频视频在线观看 | 四虎精品在线观看 | 精品久久伦理中文字幕 | 亚洲婷婷在线视频 | 91传媒制片厂果冻有限公司 | 成人a级特黄毛片 | 日韩精品一区二区 | 国产精品免费看久久久香蕉 | 无遮18禁在线永久免费观看挡 | 午夜欧美精品久久久久久久久 | sss在线观看免费视频 | 99久久精品自在自看国产 | 亚洲码在线观看 |