1. 程式人生 > 其它 >JVM指令 bytecode invokespecial

JVM指令 bytecode invokespecial

本文譯自:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokespecial

invokespecial

操作

呼叫例項初始化,父類初始化和私有方法。

格式

invokespecial
indexbyte1
indexbyte2

編碼

invokespecial= 183 (0xb7)

運算元棧

...,objectref, [arg1, [arg2...]] →

描述

無符號indexbyte1andindexbyte2用來構造一個指向當前類的執行時常量池索引,索引值通過(indexbyte1<< 8) |indexbyte2.構造得出。執行時常量池在該索引的位置必須為一個方法型別的符號引用,該符號引用給出了該方法的名稱和描述以及包含該方法的類的符號引用。該方法被解析。最終,如果該方法是protected的,並且是當前類父類的成員方法,但沒有在當前類所屬的執行時package中宣告,那麼,objectref的型別要麼為當前類,要麼為當前類的子類。

下一步,如果下列條件不同時成立,則當前方法被選為將要呼叫的方法:

  • 當前類設定了ACC_SUPER標記。
  • 該方法所屬類為當前類的父類。
  • 該方法不是例項初始化方法。

如果上述條件全部成立,則實際呼叫的方法按照如下過程進行查詢,假設C為當前類的直接父類。

  • 如果C包含了和該方法一樣的名稱和描述符宣告,則C中的該宣告則為查詢結果,超找結束。
  • 否則,在C的直接父類中執行第一步的查詢,該查詢迭代進行。
  • 否則,丟擲AbstractMethodError錯誤。

Objectref必須為引用型別,在運算元棧中,nargs個引數必須緊跟在objectref後面,並且在個數,型別和順序上必須和上述步驟查詢到的方法一致。

如果該方法是同步的(synchronized),則在與objectref關聯的監視器上執行enter或reenter操作,就像在當前執行緒中執行monitorenter指令一樣。

如果該方法不是native的,nargs個引數和objectref從棧中彈出,在當前JVM棧中為該方法建立一個新的棧幀。Objectref和nargs個引數值連續存入新棧幀的區域性變量表。Objectref存入slot0,arg1存入slot1(或者,如果arg1為long或double型別,則佔連續兩個slot,為slot1,slot2),以此類推。任何float型別的變數在存入區域性變量表之前都會先進行值集轉換。新棧幀成為當前棧幀,JVM PC設定為新方法的第一條指令,程式執行從該方法第一條指令繼續。

如果該方法是native的,並且平臺相關的實現程式碼尚未繫結到當前JVM,就這樣(譯者:不再繫結?)。nargs個引數和objectref從運算元棧中彈出,作為引數依次傳遞給實現程式碼作為區域性變數。任何float型別的變數在存入區域性變量表之前都會先進行值集轉換。引數的傳遞和程式碼執行方式依賴於具體的實現方式,當方法返回時,發生如下情形:

  • 如果native方法是同步的(synchronized),則和objectref關聯的監視器被更新並可能退出,就像在當前執行緒中執行monitorexit指令一樣。
  • 如果方法有返回值,則該平臺相關的返回值按照平臺相關的實現方式轉換成該方法的返回型別,並壓入運算元棧。

連結異常

在對該方法的符號引用進行解析時,任何與方法解析相關的異常都可能被丟擲。

否則,如果解析出的方法為例項初始化方法,並且其宣告所在類與當前指令符號引用的類不一致,則會丟擲NoSuchMethodError錯誤。

否則,如果解析出的方法是類方法(static),則invokespecial指令會丟擲IncompatibleClassChangeError錯誤。

執行時異常

否則,如果objectref是null,則invokespecial指令將丟擲NullPointerException異常。

否則,如果沒有方法和對應的名字和描述符匹配,則invokespecial指令將丟擲AbstractMethodError錯誤。

否則,如果解析出的方法是native的,但實現程式碼無法被繫結,則invokespecial指令將丟擲UnsatisfiedLinkError錯誤。

備註

Invokespecialinvokevirtual的區別在於,後者對方法的呼叫基於物件的class型別,而前者用來呼叫當前類的例項化方法,私有方法以及父類的方法(譯者:感覺此處有誤,應該是父類的例項化方法)。

早在JDK1.0.2之前,invokespecial使用invokevirtual的名字。

nargs個引數並不一定就對應nargs個區域性變數,對於long或double型別的引數值就需要連續兩個區域性變數的位置來儲存,這時,nargs個引數的傳遞就需要多於nargs個的區域性變數位置。

博主長期對外收徒,歡迎諮詢。
《程式語言設計和實現》《MUD遊戲開發》《軟體破解和加密》《遊戲輔助外掛》《JAVA開發》 以上課程非誠勿擾!



=================================
QQ:184377367
GOLang Q群:6848027
電子電路入門群 436173132
C/C++/QT群 1414577
微控制器嵌入式群 306312845
MUD/LIB/巫師交流群 391486684
java/springboot/hadoop/ 群 4915800
WEB前端開發交流群 214737701
作業系統研發群:15375777
Linux公社Q群:812742841
彙編/輔助/破解新手群:755783453
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。