国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

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

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 方法調用之動態分派(詳解)就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 免费黄色在线观看 | 亚洲国产高清高潮精品美女 | 国产韩国精品一区二区三区 | 亚洲高清在线 | 日韩成人在线播放 | 久久久一区二区三区 | 青青草原综合久久大伊人精品 | 久久精品一区二区 | 精品成人18 | 毛片免费播放 | 精品免费国产一区二区三区 | 国产精品99在线观看 | 日韩一区二区三区在线视频 | 一区二区三区日韩在线 | 国产精品久久久久久久免费大片 | 久久99国产精一区二区三区 | 免费午夜视频 | 亚洲黄色特级片 | 国产欧美精品区一区二区三区 | 国产成人精品免费视频大全最热 | 天天干在线影院 | 欧美日韩综合视频 | 亚洲伊人久久综合 | 亚洲欧美中文字幕 | 大象一区 | 成人1区 | 亚洲一区在线视频 | 网站色 | 91视频.com| av短片在线观看 | 狠狠色狠狠色合久久伊人 | 亚洲精品成人 | 99在线视频播放 | 成人午夜免费视频 | 操操操操操操 | 亚洲国产精品久久 | 久久精品久久久 | 成人小视频在线观看 | 国内久久精品 | 亚洲精品一区二三区不卡 | 国产麻豆乱码精品一区二区三区 |