Java位元組碼指令

來源:互聯網
上載者:User

標籤:war   入棧   3.4   dup   相加   結果   add   get   lcm   

1. 簡介

Java虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的數字(稱為作業碼)以及跟隨其後的零至多個代表此操作所需參數(稱為運算元)而構成。

由於Java虛擬機器採用面向運算元棧而不是寄存器的架構,所以大多數的指令都不包含運算元,只有一個作業碼。

Java虛擬機器作業碼的長度為一個位元組(即0~255),這意味著指令集的作業碼總數不可能超過256條。

2. 位元組碼和資料類型

在Java虛擬機器的指令集中,大多數的指令都包含了其操作所對應的資料類型資訊。例如,iload指令用於從局部變數中載入int型的資料到運算元棧中,而fload指令載入的則是float類型的資料。

大部分與資料類型相關的位元組碼指令,它們的作業碼助記符都有特殊的字元來表明專門為哪種資料類型服務:i代表對int類型的資料操作,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。也有一些指令的助記符中沒有明確地指明操作類型的字母,如arraylength指令。

如果每一種與資料類型相關的指令都支援Java虛擬機器所有運行時資料類型的話,那指令的數量就會超出一個位元組所能標示的數量範圍了。因此,Java虛擬機器的指令集對於特定的操作只提供了有限的類型相關指令去支援它,換句話說,指令集將會故意被設計成非完全獨立的,有一些單獨的指令可以在必要的時候用來將一些不支援的類型轉換為可被支援的類型。

3. 位元組碼分類介紹3.1 載入和儲存指令

載入和儲存指令用於將資料在棧幀中的局部變數表和運算元棧之間來回傳輸。

  • 將一個局部變數載入到操作棧:iload,iload_<n>
  • 將一個數值從運算元棧儲存到局部變數表:istore,istore_<n>
  • 將一個常量載入到運算元棧:bipush
  • 擴充局部變數表的訪問索引的指令:wide 

其中iload_<n>代表了一組指令,代表了iload_0,iload_1,iload_3這幾條指令。這幾組指令都是某個帶有一個運算元的通用指令的特殊形式,對於這若干組特殊指令來說,他們省略了顯式的運算元,不需要進行取運算元的動作。實際上運算元就隱含在指令中。例如,iload_0的語義與運算元為0時的iload指令語義完全一致。

3.2 運算指令

運算或算術指令用於對兩個運算元棧上的值進行某種特定運算,並把結果重新存入到操作棧頂。大體上算術指令可以分為兩種:對整型資料進行運算的指令與對浮點型資料進行運算的指令。無論是哪種算術指令,都使用Java虛擬機器的資料類型,由於沒有直接支援byte、short、char和boolean類型的算術指令,對於這類資料的運算,應使用操作int類型的指令代替。整數與浮點數的算術指令在溢出和被零除的時候也有各自不同的行為表現,所有的算術指令如下:

  • 加法指令:iadd,ladd,fadd,dadd
  • 減法指令:isub,lsub,fsub,dsub
  • 乘法指令:imul,lmul,fmul,dmul
  • 除法指令:idiv,ldiv,fdiv,ddiv
  • 求餘指令:irem,lrem,frem,drem
  • 取反指令:ineg,lneg,fneg,dneg
  • 位移指令:ishl,ishr,iushr,lshl,lshr,lushr
  • 按位或指令:ior,lor
  • 按位與指令:iand,land
  • 按位異或指令:ixor,lxor
  • 局部變數自增指令:iinc
  • 比較指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp

資料運算可能會導致溢出,例如:兩個很大的正整數相加,結果可能會是一個負數,其實Java虛擬機器規範沒有明確定義過整型資料溢出的具體運算結果,僅規定了在處理整型資料時,只有除法指令(idiv和ldiv)以及求餘指令(irem和lrem)中當出現除數為零時會導致虛擬機器拋出ArithmeticException溢出,其餘任何整型數運算情境都不應該拋出運行時異常。

3.3 類型轉換指令

類型轉換指令可以將兩種不同的數實值型別進行相互轉換,這些轉換操作一般用於實現使用者代碼中的顯式類型轉換操作。

Java虛擬機器直接支援以下數實值型別的寬化類型轉換(Widening Numeric Conversions,即小範圍類型向大範圍類型的安全轉換)

  • int類型到long,float或double
  • long類型到float,double
  • float類型到double

相對的,處理窄化類型轉換(Narrowing Numberic Conversions)時,必須顯式地使用轉換指令來完成,這些轉換執行包括:i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l和d2f。窄化類型轉換可能會導致轉換結果產生不同的加號或減號、不同的數量級的情況,轉換過程很可能會導致數值的精度丟失。

儘管資料類型窄化轉換可能會發生上限溢出、下限溢出和精度丟失等情況,但是Java虛擬機器規範中明確規定數實值型別的窄化轉換指令永遠不可能導致虛擬機器拋出運行時異常。

3.4 對象建立和訪問指令

雖然類執行個體和數組都是對象,但Java虛擬機器對類執行個體和數組的建立與操作使用了不同的位元組碼指令,指令如下:

  • 建立類執行個體的指令:new
  • 建立數組的指令:newarray,anewarray,multianewarray
  • 訪問類欄位和執行個體欄位的指令:getfield,putfield,getstatic,putstatic
  • 把一個數組元素載入到運算元棧的指令:baload,caload,saload,iaload,laload,faload,daload,aaload
  • 將一個運算元棧的值儲存到數組元素中的指令:bastore,castore,sastore,iastorefastore,dastore,aastore
  • 取數組長度的指令:arraylength
  • 檢查類執行個體類型的指令:instanceof,checkcast
3.5 運算元棧管理指令

如同操作一個普通資料結構中的堆棧那樣,Java虛擬機器提供了一些用於直接操作運算元棧的指令,包括:

  • 將運算元棧的棧頂一個或兩個元素出棧:pop,pop2
  • 複製棧頂一個或兩個數值並將複製值或雙份的複製值重新壓入棧頂:dup,dup2,dup_x1,dup2_x1,dup_x2,dup2_x2
  • 將棧最頂端的兩個數值互換:swap
3.6 控制轉移指令

控制轉移指令可以讓Java虛擬機器有條件或無條件地從指定的位置指令而不是控制轉移指令的下一條指令繼續執行程式,從概念性模型上理解,可以認為控制轉移指令就是在有條件或無條件地修改PC寄存器的值。控制轉移指令如下:

  • 條件分支:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnonnull,if_icmpeq,if_icmpne,if_icmplt,if_icmpgt,if_icmple,if_icmpge,if_acmpeq和if_acmpne
  • 複合條件分支:tableswitch,lookupswitch
  • 無條件分支:goto,goto_w,jsr,jsr_w,ret
3.7 方法調用和返回指令
  • invokevirtual:指令用於調用對象的執行個體方法,根據對象的實際類型進行指派,這也是Java語言中最常見的方法指派方式‘;
  • invokeinterface:指令用於調用介面方法,它會在運行時搜尋一個實現了這個介面方法的對象,找到合適的方法進行調用;
  • invokespecial:用於調用一些需要特殊處理的執行個體方法,包括執行個體初始化方法、私人方法和父類方法;
  • invokestatic:用於調用類方法(static方法)
  • invokedynamic:用於在運行時動態解析出調用點限定符所引用的方法,並執行該方法,前面4條調用指令的指派邏輯都固化在Java虛擬機器內部,而invokedynamic指令的指派邏輯是由使用者所設定的引導方法決定的。

方法調用指令與資料類型無關,而方法返回指令時根據傳回值的類型區別的,包括ireturn(傳回值是boolean,byte,char,short和int),lreturn,freturn,dreturn和areturn,另外還有一條return指令供void方法,執行個體初始化方法以及類和介面的類初始化方法使用。

3.8 異常處理指示

在Java程式中顯式拋出異常的操作(throw語句)都由athrow指令來實現。

Java虛擬機器規範還規定了許多運行時異常會在其他Java虛擬機器指令檢測到異常狀況時自動拋出。

而在Java虛擬機器中,處理異常(catch語句)不是由位元組碼指令來實現的,而是採用異常表來完成。

3.9 同步指令

Java虛擬機器可以支援方法級的同步和方法內部一段指令序列的同步,這兩種同步結構都是使用管程(Monitor)來支援的。

Java虛擬機器的指令集中有monitorenter和monitorexit兩條指令來支援synchronized關鍵字的語義。

編譯器必須確保無論方法通過何種方式完成,方法中調用過的每條monitorenter指令都必須執行其對於的monitorexit指令,而無論這個方法是正常結束還是異常結束。

 

Java位元組碼指令

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.