一、invokevirtual指令
invokevirtual #3 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
在Java虛擬機中,invokevirtual指令是用來調用對象實例方法的指令。它的操作碼是0xb6,操作數需要指定要調用的方法的符號引用。invokevirtual指令在解析階段進行動態綁定,即在執行該指令時再決定具體要調用的方法。
在上面的示例中,我們調用了PrintStream對象的println方法,我們可以通過符號引用的方式傳遞方法的參數信息和返回值信息。在執行時,Java虛擬機會查找並調用對應的println方法。
二、invokevirtual_quick
invokevirtual_quick #3 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
在invokevirtual指令的執行過程中,Java虛擬機需要進行方法查找和動態綁定,這個過程可能比較耗時。為此,Java虛擬機引入了invokevirtual_quick指令來進行快速調用。
在調用同一個類中的方法時,invokevirtual_quick指令能夠直接找到方法並調用,因此這個過程會更加快速。需要注意的是,如果在子類中重寫了父類的這個方法,那麼當使用invokevirtual_quick指令時,依然會調用父類的方法。
三、invokevirtual過程
Java虛擬機在執行invokevirtual指令時,需要進行以下步驟:
Step1. 查找符號引用所對應的方法。
Java虛擬機首先通過符號引用中的類信息,查找該類或其父類中是否存在符合方法簽名的方法,並返回方法的直接引用。
Step2. 檢查訪問許可權。
如果找到了方法的直接引用,Java虛擬機需要檢查當前類是否有許可權訪問該方法。
Step3. 進行動態綁定。
如果訪問許可權檢查通過,Java虛擬機需要判斷該方法是否為虛方法,並進行動態綁定。動態綁定的過程中,Java虛擬機會查找符合該對象實際類型的方法,如果找到,則調用這個方法。
四、invokevirtual指令的含義
invokevirtual指令主要用於調用對象實例方法,它能夠在運行時動態綁定方法,保證程序的靈活性與擴展性。而invokevirtual_quick指令則更加高效,適用於同一個類中的方法調用。
五、invokevirtual和invokeinterface
invokevirtual指令和invokeinterface指令都用於調用介面或類中的方法,它們之間的區別在於invokeinterface指令在調用前需要先通過介面映射指針表(ITable)查找介面方法所對應的方法,在動態綁定時也需要進行介面方法表(VTable)的查找。
由於invokeinterface指令需要進行兩次表的查找,因此其速度要比invokevirtual指令慢,同時還要注意介面映射指針表中方法的順序和排列方式對性能的影響。
完整示例代碼
public class Example { public static void main(String[] args) { Parent parent = new Child(); parent.foo(); } } class Parent { public void foo() { System.out.println("Parent"); } } class Child extends Parent { public void foo() { System.out.println("Child"); } }
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/220048.html