java字節碼指令集


字節碼指令集

  Java虛擬機的指令由一個字節長度的、代表着某種特定操作含義的操作碼(Opcode)以及跟隨其后的零至多個代表此操作所需參數的操作數(Operands)所構成。

  對於大部分為與數據類型相關的字節碼指令,他們的操作碼助記符中都有特殊的字符來表明專門為哪種數據類型服務:i代表對int類型的數據操作,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。

  加載和存儲指令:

將一個局部變量加載到操作棧的指令包括有:iload、iload_<n>、lload、lload_<n>、fload、fload_<n>、dload、dload_<n>、aload、aload_<n>
將一個數值從操作數棧存儲到局部變量表的指令包括有:istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_<n>、dstore、dstore_<n>、astore、astore_<n>
將一個常量加載到操作數棧的指令包括有:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_<i>、lconst_<l>、fconst_<f>、dconst_<d>
擴充局部變量表的訪問索引的指令:wide

  運算指令:

(運算之后的結果會自動入棧)

加法指令: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虛擬機對於寬化類型轉換直接支持,並不需要指令執行,包括:

int類型到long、float或者double類型
long類型到float、double類型
float類型到double類型

  窄化類型轉換指令包括有:i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l和d2f。但是窄化類型轉換很可能會造成精度丟失。

  對象創建與操作指令:

創建類實例的指令:new
創建數組的指令:newarray,anewarray,multianewarray
訪問類字段(static字段,或者稱為類變量)和實例字段(非static字段,或者成為實例變量)的指令:getfield、putfield、getstatic、putstatic
把一個數組元素加載到操作數棧的指令:baload、caload、saload、iaload、laload、faload、daload、aaload
將一個操作數棧的值儲存到數組元素中的指令:bastore、castore、sastore、iastore、fastore、dastore、aastore
取數組長度的指令:arraylength
檢查類實例類型的指令:instanceof、checkcast

  操作數棧管理指令:

  Java虛擬機提供了一些用於直接操作操作數棧的指令,包括:pop、pop2、dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2和swap

  控制轉移指令:

條件分支: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

  方法調用和返回指令:

invokevirtual指令用於調用對象的實例方法,根據對象的實際類型進行分派(虛方法分派),這也是Java語言中最常見的方法分派方式。
invokeinterface指令用於調用接口方法,它會在運行時搜索一個實現了這個接口方法的對象,找出適合的方法進行調用。
invokespecial指令用於調用一些需要特殊處理的實例方法,包括實例初始化方法(§2.9)、私有方法和父類方法。
invokestatic指令用於調用類方法(static方法)。

(上面4個invoke*調用之后的結果依舊是在操作棧的)

而方法返回指令則是根據返回值的類型區分的,包括有ireturn(當返回值是boolean、byte、char、short和int類型時使用)、lreturn、freturn、dreturn和areturn,另外還有一條return指令供聲明為void的方法、實例初始化方法、類和接口的類初始化方法使用

  拋出異常指令:

athrow

 關於Java虛擬機中的字節碼指令

源代碼經過編譯器編譯之后便會生成一個字節碼文件,字節碼是一種二進制的類文件,它的內容是JVM的指令,而不像C、C++經由編譯器直接生成機器碼。我們不用擔心生成的字節碼文件的兼容性,因為所有的JVM全部遵守Java虛擬機規范,也就是說所有的JVM環境都是一樣的,這樣一來字節碼文件可以在各種JVM上運行。 當然也包括KVM。

 

每一個線程都有一個保存幀的棧。在每一個方法調用的時候創建一個幀。一個幀包括了三個部分:操作棧,局部變量數組,和一個對當前方法所屬類的常量池的引用。

局部變量數組也被稱之為局部變量表,它包含了方法的參數,也用於保存一些局部變量的值。參數值得存放總是在局部變量數組的index0開始的。如果當前幀是由構造函數或者實例方法創建的,那么該對象引用將會存放在location0處,然后才開始存放其余的參數。

局部變量表的大小由編譯時決定,同時也依賴於局部變量的數量和一些方法的大小。操作棧是一個(LIFO)棧,用於壓入和取出值,其大小也在編譯時決定。某些opcode指令將值壓入操作棧,其余的opcode指令將操作數取出棧。使用它們后再把結果壓入棧。操作棧也用於接收從方法中返回的值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM