JVM字節代碼指令

字節代碼指令由一個標識該指令的操作碼和固定數目的參數組成:

  • 操作碼是一個無符號字節值——即字節代碼名,由助記符號標識。例如,操作碼 0 用助 記符號 NOP 表示,對應於不做任何操作的指令。
  • 參數是靜態值,確定了精確的指令行爲。它們緊跟在操作碼之後給出。比如GOTO標記 指令(其操作碼的值爲 167)以一個指明下一條待執行指令的標記作爲參數標記。不要 將指令參數與指令操作數相混淆:參數值是靜態已知的,存儲在編譯後的代碼中,而 操作數值來自操作數棧,只有到運行時才能知道。

 

字節代碼指令可以分爲兩類:一小組指令,設計用來在局部變量和操作數棧之間傳送值;其 他一些指令僅用於操作數棧:它們從棧中彈出一些值,根據這些值計算一個結果,並將它壓回棧 中。

 

ILOAD, LLOAD, FLOAD, DLOAD ALOAD 指令讀取一個局部變量,並將它的值壓到操 作數棧中。它們的參數是必須讀取的局部變量的索引 iILOAD 用於加載一個 booleanbytecharshort int 局部變量。LLOADFLOAD DLOAD 分別用於加載 longfloat double 值。(LLOAD DLOAD 實際加載兩個槽 i i+1)。最後,ALOAD 用於加載任意非基元值,即對 象和數組引用。與之對應,ISTORELSTOREFSTOREDSTORE ASTORE 指令從操作數棧 中彈出一個值,並將它存儲在由其索引 i 指定的局部變量中。

 

可以看到,xLOAD xSTORE 指令被賦入了類型(事實上,下面將要看出,幾乎所有指令 都被賦予了類型)。它用於確保不會執行非法轉換。實際上,將一個值存儲在局部變量中,然後 再以不同類型加載它,是非法的。例如,ISTORE 1 ALOAD 1 序列是非法的——它允許將一個 任意內存位置存儲在局部變量 1 中,並將這個地址轉換爲對象引用!但是,如果向一個局部變 量中存儲一個值,而這個值的類型不同於該局部變量中存儲的當前值,卻是完全合法的。這意味 着一個局部變量的類型,即這個局部變量中所存值的類型可以在方法執行期間發生變化。

 

上面已經說過,所有其他字節代碼指令都僅對操作數棧有效。它們可以劃分爲以下類別(見 附件 A.1):

 

這些指令用於處理棧上的值:POP彈出棧頂部的值,DUP壓入頂部棧值的一個副本, SWAP 彈出兩個值,並按逆序壓入它們,等等。

 

常量 這些指令在操作數棧壓入一個常量值:ACONST_NULL壓入nullICONST_0壓入 int 值 0,FCONST_0 壓入 0fDCONST_0 壓入 0dBIPUSH b 壓入字節值 bSIPUSH s 壓入 short sLDC cst 壓入任意 intfloatlongdoubleString class1 常量 cst,等等。

 

算術與邏輯 這些指令從操作數棧彈出數值,合併它們,並將結果壓入棧中。它們沒有任何 參數。xADDxSUBxMULxDIV xREM 對應於+-*/%運算,其中 x ILF D 之一。類似地,還有其他對應於<<>>>>>|&^運算的指令,用於 處理intlong值。

 

類型變換 這些指令從棧中彈出一個值,將其轉換爲另一類型,並將結果壓入棧中。它們對 應於 Java 中的類型轉換表達式。I2F, F2D, L2D 等將數值由一種數值類型轉換爲另一種 類型。CHECKCAST t 將一個引用值轉換爲類型 t

 

對象 這些指令用於創建對象、鎖定它們、檢測它們的類型,等等。例如,NEWtype指令將 一個 type 類型的新對象壓入棧中(其中 type 是一個內部名)。

 

字段 這些指令讀或寫一個字段的值。GETFIELD owner name desc 彈出一個對象引用,並 壓和其 name 字段中的值。PUTFIELD owner name desc 彈出一個值和一個對象引用,並 將這個值存儲在它的 name 字段中。在這兩種情況下,該對象都必須是 owner 類型,它 的字段必須爲 desc 類型。GETSTATIC PUTSTATIC 是類似指令,但用於靜態字段。

 

方法 這些指令調用一個方法或一個構造器。它們彈出值的個數等於其方法參數個數加 1 (用於目標對象),並壓回方法調用的結果。INVOKEVIRTUAL owner name desc 調用在 類 owner 中定義的 name 方法,其方法􏰂述符爲 descINVOKESTATIC 用於靜態方法, INVOKESPECIAL 用於私有方法和構造器,INVOKEINTERFACE 用於接口中定義的方 法。最後,對於 Java 7 中的類,INVOKEDYNAMIC 用於新動態方法調用機制。

 

數組 這些指令用於讀寫數組中的值。xALOAD指令彈出一個索引和一個數組,並壓入此索 引處數組元素的值。xASTORE 指令彈出一個值、一個索引和一個數組,並將這個值存 儲在該數組的這一索引處。這裏的 x 可以是 ILFD A,還可以是 BC S

 

跳轉 這些指令無條件地或者在某一條件爲真時跳轉到一條任意指令。它們用於編譯iffordowhilebreak continue 指令。例如,IFEQ label 從棧中彈出一個 int 值,如果這個值爲 0,則跳轉到由這個 label 指定的指令處(否則,正常執行下一 條指令)。還有許多其他跳轉指令,比如 IFNE IFGE。最後,TABLESWITCH

LOOKUPSWITCH 對應於 switch Java 指令。

 

返回 最後,xRETURNRETURN指令用於終止一個方法的執行,並將其結果返回給調用 者。RETURN 用於返回 void 的方法,xRETURN 用於其他方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章