JVM學習-動態鏈接和方法返回地址

動態鏈接–指向運行時常量池的方法引用
  • 每一個棧幀內部包含一個指向運行時常量池中該棧幀所屬方法的引用,包含這個引用的目的為了支持當前方法的代碼能夠實現動態鏈接(Dynamic Linking),如invokednamic指令。
  • 在Java源文件被編譯到字節碼文件中時,所有的變量和方法引用都作為符號引用保存在class文件的常量池中,比如一個方法調用了另一個方法,就是通過常量池中方法的符號引用來表示的,動態鏈接的作用是為了將這些符號引用轉換為調用方法的直接引用。
    在這里插入圖片描述
為什么需要常量池?

常量池的作用,是為了提供一些符號和常量,便于指令的識別

方法的調用

在JVM中,將符號引用轉換為調用方法的直接引用與方法的綁定機制相關,綁定機制分為早期綁定和晚期綁定,綁定是一個字段、方法或者類在符號引用被替換為直接引用的過程,這僅僅發生一次。

  • 早期綁定:指被調用的目標方法如果在編譯期可知,且運行期保持不變時,即可將這個方法與所屬的類型進行綁定,這樣一來,由于明確了被調用的目標方法究竟是哪一個,因此也可以使用靜態鏈接的方式將符號引用轉換為直接引用
  • 晚期綁定:如果被調用的方法在編譯期無法被確定下來,只能夠在程序運行期根據實際的類型綁定相關的方法,稱為晚期綁定
靜態鏈接

當一個字節碼文件被裝載進JVM內部時,如果被調用的目標方法在編譯期可知,且運行期間保持不變,這種情況下將調用方法的符號引用轉換為直接引用的過程稱為靜態鏈接

動態鏈接

如果被調用方法在編譯期無法被確定下來,只能夠在程序運行期調用方法的符號引用轉換為直接引用,由于這種引用轉換過程具備動態性,因此被稱為動態鏈接

class Animal {public void eat(){System.out.println("動物進食");}
}
interface Huntable {void hunt();
}
class Dog extends Animal implements Huntable {@Overridepublic void eat() {System.out.println("狗吃骨頭");}@Overridepublic void hunt() {System.out.println("狗拿耗子,多管閑事");}
}
class Cat extends Animal implements Huntable {public Cat() {super();   //早期綁定}public Cat(String name) {this();    //早期綁定}@Overridepublic void eat() {super.eat();       //早期綁定System.out.println("貓吃魚");}@Overridepublic void hunt() {System.out.println("貓拿耗子,天經地義");}
}
public class AnimalTest {public void showAnimal(Animal animal) {animal.eat(); //晚期綁定}public void showHunt(Huntable h) {h.hunt(); //晚期綁定}
}
虛方法和非虛方法
  • 非虛方法:方法在編譯期就確定了具體的調用版本,這個版本在運行時是不可變的,這種方法稱為非虛方法。

  • 靜態方法、私有方法、final方法、實例構造器、父類方法都是非虛方法。

  • 其它方法為虛方法

  • 普通調用指令

    • invokestatic:調用靜態方法,解析階段確定唯一方法版本
    • invokespecial:調用方法,私有及父類方法,解析階段確定唯一方法版本
    • invokevirtual:調用所有虛方法
    • invokeinterface:調用接口方法
  • 動態調用指令

    • invokedynamic:動態解析出需要調用的方法,然后執行
      普通調用指令固化在虛擬機內部,方法的調用執行不可人為干預,而invokedynamic指令則支持由用戶確定方法版本,其中invokestatic指令和invokespecial指令調用的方法稱為非虛方法,其余的(final修飾的除外)稱為虛方法
      靜態類型語言是判斷變量自身的類型信息,動態類型語言是判斷變量值的類型信息,變量沒有類型信息,變量值才有類型信息。
class Father {public Father() {System.out.println("father構造器");}public static void showStatic(String str) {System.out.println("father " + str);}public final void showFinal() {System.out.println("father show final");}public void showCommon() {System.out.println("father 普通方法");}
}
public class Son extends Father{public Son() {super();}public Son(int age) {this();}//非重寫父類的方法,靜態方法不允許重寫public static void showStatus(String str) {System.out.println("son " + str);}private void showPrivate(String str) {System.out.println("son private " + str);}public void show() {//invokestaticshowStatic("lotus.com");//invokestaticsuper.showStatic("goods!");//invokespecialshowPrivate("hellow!");//invokespecialsuper.showCommon();//invokevirtual,此方法聲明有final,不能被子類重寫,此方法為非虛方法showFinal();//invokevirtualshowCommon();info();MethodInterface in = null;//invokeinterfacein.methodA();}private void info() {}public void display(Father f) {f.showCommon();}public static void main(String[] args) {Son so = new Son();so.show();}
}
interface MethodInterface {void methodA();
}
@FunctionalInterface
interface Func {public boolean func(String str);
}
public class Lambda {public void lambda(Func func) {return;}public static void main(String[] args) {Lambda lambda = new Lambda();//invokedynamicFunc func = s-> {return true;};//invokedynamiclambda.lambda(s-> {return true;});}
}
方法重寫本質
  1. 找到操作數棧頂的第一個元素所執行的對象的實際類型,記作C
  2. 如果過程結束,不通過類型C中找到與常量中的描述符符合簡單名稱都相符的方法,則進行訪問權限校驗,如果通過則返回這個方法的直接引用,查找不到,則返回java.lang.IllegalAccessError異常
  3. 否則,按繼承關系從下向上依次對C的各個父類進行第2步搜索和驗證過程
  4. 如果始終沒有找到合適的方法,則拋出java.lang.AbstractMethodError異常。
虛方法表
  • 在面向對象的編程中,會頻繁的使用到動態分派,如果在每次動態分派的過程中都要重新在類的方法元數據中搜索合適的目標的話,就可能影響到執行效率,因此,為了提高性能,JVM采用在類的方法區建立一個虛方法表(非虛方法不會出現在表中)來實現,使用索引表代替查找
  • 每個類中都有一個虛方法表,表中存放各個方法的實際入口
  • 虛方法表會在類加載的鏈接階段被創建并開始初使化,類的變量初使值準備完成之后,JVM會把該類的方法一也初始化完畢
方法返回地址
  • 存放調用該方法的PC寄存器的值
  • 一個方法結束,有兩種方式:
    • 正常執行完成
      • 一個方法在正常調用完成之后究竟需要使用哪一個返回指令還需要根據方法返回值的實際數據類型而定
      • 在字節碼指令中,返回指令包含ireturn(當返回值是boolean,byte,char,short,int類型時),lreturn,freturn,dreturn以及areturn,另外還有一個return指令供聲明為void方法,實例化初始化方法、類和接口的初始化方法使用。
    • 出現未處理的異常,非正常退出
      • 方法執行過程中拋出異常時的異常處理,存儲在一個異常處理表,方便在發生異常的時候找到處理異常的代碼。
  • 無論哪種方式退出,在方法退出后都返回到該方法被調用的位置,方法正常退出時,調用者PC寄存器的值做為返回地址,好調用該方法的指令的下一條指令地址,而通過異常退出的,返回地址是要通過異常表來確定,棧幀中一般不會保存這部分信息。
import java.io.FileReader;
import java.io.IOException;
import java.util.Date;/*** Administrator* 2024/5/17*/
public class ReturnAddressTest {//ireturnpublic boolean methodBoolean() {return false;}//ireturnpublic byte methodByte(){return 0;}//ireturnpublic short methodShort(){return 0;}//ireturnpublic char methodChar(){return 'a';}//ireturnpublic int methodInt(){return 0;}//lreturnpublic long methodLong(){return 0L;}//freturnpublic float methodFloat(){return 0.0f;}//dreturnpublic double methodDouble(){return 0.0;}//areturnpublic String methodString() {return null;}//areturnpublic Date methodDate(){return null;}//returnpublic void methodVoid(){}static {int i = 10;}public void method2() {methodVoid();try {method1();} catch (IOException e) {e.printStackTrace();}}public void method1() throws IOException {FileReader fr = new FileReader("lotus.txt");char[] cBuffers = new char[1024];int len;while ((len = fr.read(cBuffers))!=-1) {String str = new String(cBuffers,0,len);System.out.println(str);}fr.close();}public static void main(String[] args) {}
}

方法返回地址本質上,方法的退出就是當前棧幀出棧的過程,此時,需要恢復上層方法的局部變量表、操作數棧、將返回值壓入調用者棧幀的操作數棧、設置PC寄存器值等,讓調用者方法繼續執行下去

正常完成出口和異常完成出口區別:通過異常完成出口退出的不會給他的上層調用者產生任何返回值

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/14362.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/14362.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/14362.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

云平臺概要設計文檔 -大綱

1. 引言 1.1 目的 本文檔的目的是提供一份詳細的技術規范,用以指導開發團隊實現云平臺的建設和部署。該文檔旨在確保所有開發人員和相關技術人員對系統的架構、組件、交互流程、數據處理及安全措施有深入的理解,從而能夠高效、一致地開發出符合預期功能和性能要求的系統。 …

JAVA:淺談JSON與JSON轉換

可能有很多人,無論是前端還是后端,無論是JAVA還是Python還是C,都應該跟JSON這種數據格式打過交道,那么有沒有仔細的想過,什么叫JSON? JSON是一種輕量級的數據交換格式。它基于JavaScript語言的對象表示法&a…

初識java——javaSE(6)抽象類與接口【求個關注!】

文章目錄 前言一 抽象類1.1 抽象類的概念1.2 抽象類的語法:1.3 抽象類與普通類的區別: 二 接口2.1 接口的概念2.2 接口的語法2.2.1 接口的各個組成2.2.2 接口之間的繼承 2.3 接口的實現接口不可以實例化對象 2.4 接口實現多態 三 Object類3.1 Object類是…

【shell】腳本練習題

案例: 1. for ping測試指網段的主機 網段由用戶輸入,例如用戶輸入192.168.2 ,則ping 192.168.2.10 --- 192.168.2.20 UP: /tmp/host_up.txt Down: /tmp/host_down.txt 2. 使用case實現成績優良差的判斷 1. for ping測試指…

Android異常及解決方式記錄

異常1:Tmp detached view should be removed from RecyclerView before it can be recycled: 解決方法: recycleView.setItemAnimator(null);

第17講:C語言內存函數

目錄 1.memcpy使用和模擬實現2.memmove使用和模擬實現3.memset函數的使用4.memcmp函數的使用 1.memcpy使用和模擬實現 void * memcpy (void * destination, const void * source, size_t num);? 函數memcpy從source的位置開始向后復制num個字節的數據到destination指向的內存…

Python面試寶典:Python中與多線程編程相關的面試筆試題(1000加面試筆試題助你輕松捕獲大廠Offer)

Python面試寶典:1000加python面試題助你輕松捕獲大廠Offer【第二部分:Python高級特性:第十三章:并發編程:第一節:多線程編程】 第十三章:并發編程第一節:多線程編程使用`threading`模塊面試題1面試題2面試題3面試題4面試題5面試題6面試題7面試題8面試題9面試題10更多面…

打豆豆game

好的,我將為您編寫一個簡單的“打豆豆”游戲。這個游戲的基本規則是這樣的: 游戲將生成一個指定大小的網格,每個格子可能包含一個豆豆。玩家可以指定一個格子,如果該格子中有豆豆,則打掉該豆豆,并得分。每…

【Java 開發】模版模式使用模版

在日常開發中,對適合的場景。使用模板模式可以幫助我們抽取公共的東西,使代碼更加優雅。本次寫了一個模版模式的使用模版,方便以后 cv。 本次是以訂單的接受、拒絕、關閉三個操作作為 demo 來寫的模板。 一、定義請求基類,不同操作…

leecode42 DP

自己的暴力想法,把圖形看成一個個碗,一段一段地算,錯誤示例 class Solution { public:int trap(vector<int>& height) {int s height.size();int sum 0,kk1;int flag 0;int p1 -1, p2 -1;for (int i 1; i < s; i) {cout<<p1<<endl;if (p1 >…

網絡安全技術與應用:遠程控制與數據庫安全

實驗準備 軟件&#xff1a;VMware Workstation Pro 虛擬機&#xff1a;Red Hat Enterprise Linux 7 服務器&#xff0c;Red Hat Enterprise Linux 7 客戶端 網絡模式&#xff1a;NAT模式 1、配置服務器及客戶端網絡 服務器IP 客戶端IP 測試相互通信 在客戶機上設置鏡像&#…

【C++刷題】優選算法——遞歸第二輯

全排列 vector<vector<int>> vv; void dfs(vector<int>& nums, vector<int>& v, vector<bool>& check) {if(v.size() nums.size()){vv.push_back(v);return;}for(int i 0; i < nums.size(); i){if(check[i] false){v.push_ba…

pillow學習5

ImageEnhance 模塊 內置的 ImageEnhance 模塊中包含了多個用于增強圖像效果的函數&#xff0c;主要用來調整圖像 的色彩、對比度、亮度和清晰度等&#xff0c;感覺上和調整電視機的顯示參數一樣。 在模塊 ImageEnhance 中&#xff0c;所有的圖片增強對象都實現一個通用的接口。…

nginx的配置以及常見命令

Nginx配置與常用命令指南 Nginx是一個高性能的HTTP和反向代理服務器&#xff0c;也是一個IMAP/POP3/SMTP服務器。由于它的穩定性、豐富的功能集、簡單的配置文件和低資源消耗&#xff0c;Nginx在全球范圍內被廣泛使用。在本文中&#xff0c;我們將介紹Nginx的基本配置和一些常…

車載網絡測試實操源碼_使用CAPL腳本模擬發送符合協議要求(Counter和CRC)的CAN報文

系列文章目錄 車載網絡測試實操源碼_使用CAPL腳本解析hex、S19、vbf文件 車載網絡測試實操源碼_使用CAPL腳本對CAN報文的Counter和CRC進行實時監控 車載網絡測試實操源碼_使用CAPL腳本模擬發送符合協議要求(Counter和CRC)的CAN報文 車載網絡測試實操源碼_使用CAPL腳本實現安全…

利用神經網絡學習語言(四)——深度循環神經網絡

相關說明 這篇文章的大部分內容參考自我的新書《解構大語言模型&#xff1a;從線性回歸到通用人工智能》&#xff0c;歡迎有興趣的讀者多多支持。 本文涉及到的代碼鏈接如下&#xff1a;regression2chatgpt/ch10_rnn/char_rnn_batch.ipynb 《循環神經網絡&#xff08;RNN&…

【移花接木】OpenCV4.8 For Java 深度學習 實時人臉檢測

學習《OpenCV應用開發&#xff1a;入門、進階與工程化實踐》一書&#xff0c;學會本文所有技能就這么簡單&#xff01; 做真正的OpenCV開發者&#xff0c;從入門到入職&#xff0c;一步到位&#xff01; 前言 我寫這篇文章之前&#xff0c;我搜索整個網絡文章跟問各種語言大模…

速賣通測評揭秘:如何選擇安全的渠道操作

許多商家對測評存在誤解&#xff0c;認為只需進行幾次測評就能迅速打造爆款。實際上&#xff0c;測評是一個需要計劃和持久性的過程&#xff0c;以便讓平臺檢測到產品的受眾程度并提高產品的曝光和權重。 在進行測評時&#xff0c;安全是首要考慮的問題。平臺可以通過設備、網…

黑馬點評1——短信篇(基于session)

&#x1f308;hello&#xff0c;你好鴨&#xff0c;我是Ethan&#xff0c;一名不斷學習的碼農&#xff0c;很高興你能來閱讀。 ??目前博客主要更新Java系列、項目案例、計算機必學四件套等。 &#x1f3c3;人生之義&#xff0c;在于追求&#xff0c;不在成敗&#xff0c;勤通…

如何使用多種算法解決LeetCode第135題——分發糖果問題

?????? 歡迎來到我的博客。希望您能在這里找到既有價值又有趣的內容&#xff0c;和我一起探索、學習和成長。歡迎評論區暢所欲言、享受知識的樂趣&#xff01; 推薦&#xff1a;數據分析螺絲釘的首頁 格物致知 終身學習 期待您的關注 導航&#xff1a; LeetCode解鎖100…