上善若水
          In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
          posts - 146,comments - 147,trackbacks - 0
          小注:去年在看《深入解析JVM》書的時候做的一些記錄,同時參考了《Java虛擬機規(guī)范》。只是對指令的一些列舉,加入了一些自己的理解。可以用來查詢。

          Java二進制指令代碼解析

          Java源碼在運行之前都要編譯成為字節(jié)碼格式(如.class文件),然后由ClassLoader將字節(jié)碼載入運行。在字節(jié)碼文件中,指令代碼只是其中的一部分,里面還記錄了字節(jié)碼文件的編譯版本、常量池、訪問權(quán)限、所有成員變量和成員方法等信息(詳見Java字節(jié)碼格式詳解)。本文主要簡單介紹不同Java指令的功能以及在代碼中如何解析二進制指令。 

          Java指令是基于棧的體系結(jié)構(gòu),大部分的指令默認的操作數(shù)在棧中。映像中ARM是基于寄存器的操作指令,而x86好像是混合寄存器和存儲器的,發(fā)現(xiàn)基于棧的操作指令確實簡單,學(xué)起來很快。不過不知道這種操作的效率怎么樣,以我自己的推測應(yīng)該是不太好的。對這方面不太了解,隨便扯幾句。 

          Java總共有200多條指令,不過很多都是重復(fù)的。我的理解,網(wǎng)絡(luò)是Java一個非常重要的特性,而且Java在設(shè)計之初就認為字節(jié)碼是要在網(wǎng)絡(luò)中傳輸?shù)模瑸榱藴p少網(wǎng)絡(luò)傳輸流量,字節(jié)碼就要盡量設(shè)計精簡、緊湊。因而Java增加了很多重復(fù)指令,比如盡量減少操作數(shù),因而我們會發(fā)現(xiàn)Java的很多指令都是沒有操作數(shù)的;并且指令中的操作數(shù)基本上都是當(dāng)無法將值放到棧中的數(shù)據(jù),比如局部變量的索引號和常量池中的索引號。 

          還有一點需要注意的是,在運行過程中,所有booleanbytecharshort都是以int類型值存在,因而對這些類型的指令操作很少。然而好像sun實現(xiàn)的虛擬機中。這些類型的數(shù)組據(jù)說不是以int類型的形式保存的,這個很奇怪。我的理解,以字對齊方式的操作效率會比較高,因而做了這種轉(zhuǎn)換,以空間換時間。 

          Java指令集(按功能分類)

          常量入棧指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          aconst_null

           

          null值入棧。

          iconst_m1

           

          -1(int)值入棧。

          iconst_0

           

          0(int)值入棧。

          iconst_1

           

          1(int)值入棧。

          iconst_2

           

          2(int)值入棧。

          iconst_3

           

          3(int)值入棧。

          iconst_4

           

          4(int)值入棧。

          iconst_5

           

          5(int)值入棧。

          lconst_0

           

          0(long)值入棧。

          lconst_1

           

          1(long)值入棧。

          fconst_0

           

          0(float)值入棧。

          fconst_1

           

          1(float)值入棧。

          fconst_2

           

          2(float)值入棧。

          dconst_0

           

          0(double)值入棧。

          dconst_1

           

          1(double)值入棧。

          bipush

          valuebyte

          valuebyte值帶符號擴展成int值入棧。

          sipush

          valuebyte1

          valuebyte2

          (valuebyte1 << 8) | valuebyte2 值帶符號擴展成int值入棧。

          ldc

          indexbyte1

          常量池中的常量值(int, float, string reference, object reference)入棧。

          ldc_w

          indexbyte1

          indexbyte2

          常量池中常量(int, float, string reference, object reference)入棧。

          ldc2_w

          indexbyte1

          indexbyte2

          常量池中常量(long, double)入棧。

           

          局部變量值轉(zhuǎn)載到棧中指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          (wide)aload

          indexbyte

          從局部變量indexbyte中裝載引用類型值入棧。

          aload_0

           

          從局部變量0中裝載引用類型值入棧。

          aload_1

           

          從局部變量1中裝載引用類型值入棧。

          aload_2

           

          從局部變量2中裝載引用類型值入棧。

          aload_3

           

          從局部變量3中裝載引用類型值入棧。

          (wide)iload

          indexbyte

          從局部變量indexbyte中裝載int類型值入棧。

          iload_0

           

          從局部變量0中裝載int類型值入棧。

          iload_1

           

          從局部變量1中裝載int類型值入棧。

          iload_2

           

          從局部變量2中裝載int類型值入棧。

          iload_3

           

          從局部變量3中裝載int類型值入棧。

          (wide)lload

          indexbyte

          從局部變量indexbyte中裝載long類型值入棧。

          lload_0

           

          從局部變量0中裝載int類型值入棧。

          lload_1

           

          從局部變量1中裝載int類型值入棧。

          lload_2

           

          從局部變量2中裝載int類型值入棧。

          lload_3

           

          從局部變量3中裝載int類型值入棧。

          (wide)fload

          indexbyte

          從局部變量indexbyte中裝載float類型值入棧。

          fload_0

           

          從局部變量0中裝載float類型值入棧。

          fload_1

           

          從局部變量1中裝載float類型值入棧。

          fload_2

           

          從局部變量2中裝載float類型值入棧。

          fload_3

           

          從局部變量3中裝載float類型值入棧。

          (wide)dload

          indexbyte

          從局部變量indexbyte中裝載double類型值入棧。

          dload_0

           

          從局部變量0中裝載double類型值入棧。

          dload_1

           

          從局部變量1中裝載double類型值入棧。

          dload_2

           

          從局部變量2中裝載double類型值入棧。

          dload_3

           

          從局部變量3中裝載double類型值入棧。

          aaload

           

          從引用類型數(shù)組中裝載指定項的值。

          iaload

           

          int類型數(shù)組中裝載指定項的值。

          laload

           

          long類型數(shù)組中裝載指定項的值。

          faload

           

          float類型數(shù)組中裝載指定項的值。

          daload

           

          double類型數(shù)組中裝載指定項的值。

          baload

           

          boolean類型數(shù)組或byte類型數(shù)組中裝載指定項的值(先轉(zhuǎn)換為int類型值,后壓棧)。

          caload

           

          char類型數(shù)組中裝載指定項的值(先轉(zhuǎn)換為int類型值,后壓棧)。

          saload

           

          short類型數(shù)組中裝載指定項的值(先轉(zhuǎn)換為int類型值,后壓棧)。

           

          將棧頂值保存到局部變量中指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          (wide)astore

          indexbyte

          將棧頂引用類型值保存到局部變量indexbyte中。

          astroe_0

           

          將棧頂引用類型值保存到局部變量0中。

          astore_1

           

          將棧頂引用類型值保存到局部變量1中。

          astore_2

           

          將棧頂引用類型值保存到局部變量2中。

          astore_3

           

          將棧頂引用類型值保存到局部變量3中。

          (wide)istore

          indexbyte

          將棧頂int類型值保存到局部變量indexbyte中。

          istore_0

           

          將棧頂int類型值保存到局部變量0中。

          istore_1

           

          將棧頂int類型值保存到局部變量1中。

          istore_2

           

          將棧頂int類型值保存到局部變量2中。

          istore_3

           

          將棧頂int類型值保存到局部變量3中。

          (wide)lstore

          indexbyte

          將棧頂long類型值保存到局部變量indexbyte中。

          lstore_0

           

          將棧頂long類型值保存到局部變量0中。

          lstore_1

           

          將棧頂long類型值保存到局部變量1中。

          lstore_2

           

          將棧頂long類型值保存到局部變量2中。

          lstroe_3

           

          將棧頂long類型值保存到局部變量3中。

          (wide)fstore

          indexbyte

          將棧頂float類型值保存到局部變量indexbyte中。

          fstore_0

           

          將棧頂float類型值保存到局部變量0中。

          fstore_1

           

          將棧頂float類型值保存到局部變量1中。

          fstore_2

           

          將棧頂float類型值保存到局部變量2中。

          fstore_3

           

          將棧頂float類型值保存到局部變量3中。

          (wide)dstore

          indexbyte

          將棧頂double類型值保存到局部變量indexbyte中。

          dstore_0

           

          將棧頂double類型值保存到局部變量0中。

          dstore_1

           

          將棧頂double類型值保存到局部變量1中。

          dstore_2

           

          將棧頂double類型值保存到局部變量2中。

          dstore_3

           

          將棧頂double類型值保存到局部變量3中。

          aastore

           

          將棧頂引用類型值保存到指定引用類型數(shù)組的指定項。

          iastore

           

          將棧頂int類型值保存到指定int類型數(shù)組的指定項。

          lastore

           

          將棧頂long類型值保存到指定long類型數(shù)組的指定項。

          fastore

           

          將棧頂float類型值保存到指定float類型數(shù)組的指定項。

          dastore

           

          將棧頂double類型值保存到指定double類型數(shù)組的指定項。

          bastroe

           

          將棧頂boolean類型值或byte類型值保存到指定boolean類型數(shù)組或byte類型數(shù)組的指定項。

          castore

           

          將棧頂char類型值保存到指定char類型數(shù)組的指定項。

          sastore

           

          將棧頂short類型值保存到指定short類型數(shù)組的指定項。

           

          wide指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          wide

           

          使用附加字節(jié)擴展局部變量索引(iinc指令特殊)。

           

          通用(無類型)棧操作指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          nop

           

          空操作。

          pop

           

          從棧頂彈出一個字長的數(shù)據(jù)。

          pop2

           

          從棧頂彈出兩個字長的數(shù)據(jù)。

          dup

           

          復(fù)制棧頂一個字長的數(shù)據(jù),將復(fù)制后的數(shù)據(jù)壓棧。

          dup_x1

           

          復(fù)制棧頂一個字長的數(shù)據(jù),彈出棧頂兩個字長數(shù)據(jù),先將復(fù)制后的數(shù)據(jù)壓棧,再將彈出的兩個字長數(shù)據(jù)壓棧。

          dup_x2

           

          復(fù)制棧頂一個字長的數(shù)據(jù),彈出棧頂三個字長的數(shù)據(jù),將復(fù)制后的數(shù)據(jù)壓棧,再將彈出的三個字長的數(shù)據(jù)壓棧。

          dup2

           

          復(fù)制棧頂兩個字長的數(shù)據(jù),將復(fù)制后的兩個字長的數(shù)據(jù)壓棧。

          dup2_x1

           

          復(fù)制棧頂兩個字長的數(shù)據(jù),彈出棧頂三個字長的數(shù)據(jù),將復(fù)制后的兩個字長的數(shù)據(jù)壓棧,再將彈出的三個字長的數(shù)據(jù)壓棧。

          dup2_x2

           

          復(fù)制棧頂兩個字長的數(shù)據(jù),彈出棧頂四個字長的數(shù)據(jù),將復(fù)制后的兩個字長的數(shù)據(jù)壓棧,再將彈出的四個字長的數(shù)據(jù)壓棧。

          swap

           

          交換棧頂兩個字長的數(shù)據(jù)的位置。Java指令中沒有提供以兩個字長為單位的交換指令。

           

          類型轉(zhuǎn)換指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          i2f

           

          將棧頂int類型值轉(zhuǎn)換為float類型值。

          i2l

           

          將棧頂int類型值轉(zhuǎn)換為long類型值。

          i2d

           

          將棧頂int類型值轉(zhuǎn)換為double類型值。

          f2i

           

          將棧頂float類型值轉(zhuǎn)換為int類型值。

          f2l

           

          將棧頂float類型值轉(zhuǎn)換為long類型值。

          f2d

           

          將棧頂float類型值轉(zhuǎn)換為double類型值。

          l2i

           

          將棧頂long類型值轉(zhuǎn)換為int類型值。

          l2f

           

          將棧頂long類型值轉(zhuǎn)換為float類型值。

          l2d

           

          將棧頂long類型值轉(zhuǎn)換double類型值。

          d2i

           

          將棧頂double類型值轉(zhuǎn)換為int類型值。

          d2f

           

          將棧頂double類型值轉(zhuǎn)換為float類型值。

          d2l

           

          將棧頂double類型值轉(zhuǎn)換為long類型值。

          i2b

           

          將棧頂int類型值截斷成byte類型,后帶符號擴展成int類型值入棧。

          i2c

           

          將棧頂int類型值截斷成char類型值,后帶符號擴展成int類型值入棧。

          i2s

           

          將棧頂int類型值截斷成short類型值,后帶符號擴展成int類型值入棧。

           

          整數(shù)運算

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          iadd

           

          將棧頂兩int類型數(shù)相加,結(jié)果入棧。

          isub

           

          將棧頂兩int類型數(shù)相減,結(jié)果入棧。

          imul

           

          將棧頂兩int類型數(shù)相乘,結(jié)果入棧。

          idiv

           

          將棧頂兩int類型數(shù)相除,結(jié)果入棧。

          irem

           

          將棧頂兩int類型數(shù)取模,結(jié)果入棧。

          ineg

           

          將棧頂int類型值取負,結(jié)果入棧。

          ladd

           

          將棧頂兩long類型數(shù)相加,結(jié)果入棧。

          lsub

           

          將棧頂兩long類型數(shù)相減,結(jié)果入棧。

          lmul

           

          將棧頂兩long類型數(shù)相乘,結(jié)果入棧。

          ldiv

           

          將棧頂兩long類型數(shù)相除,結(jié)果入棧。

          lrem

           

          將棧頂兩long類型數(shù)取模,結(jié)果入棧。

          lneg

           

          將棧頂long類型值取負,結(jié)果入棧。

          (wide)iinc

          indexbyte

          constbyte

          將整數(shù)值constbyte加到indexbyte指定的int類型的局部變量中。

           

          浮點運算

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          fadd

           

          將棧頂兩float類型數(shù)相加,結(jié)果入棧。

          fsub

           

          將棧頂兩float類型數(shù)相減,結(jié)果入棧。

          fmul

           

          將棧頂兩float類型數(shù)相乘,結(jié)果入棧。

          fdiv

           

          將棧頂兩float類型數(shù)相除,結(jié)果入棧。

          frem

           

          將棧頂兩float類型數(shù)取模,結(jié)果入棧。

          fneg

           

          將棧頂float類型值取反,結(jié)果入棧。

          dadd

           

          將棧頂兩double類型數(shù)相加,結(jié)果入棧。

          dsub

           

          將棧頂兩double類型數(shù)相減,結(jié)果入棧。

          dmul

           

          將棧頂兩double類型數(shù)相乘,結(jié)果入棧。

          ddiv

           

          將棧頂兩double類型數(shù)相除,結(jié)果入棧。

          drem

           

          將棧頂兩double類型數(shù)取模,結(jié)果入棧。

          dneg

           

          將棧頂double類型值取負,結(jié)果入棧。

           

          邏輯運算——移位運算

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          ishl

           

          左移int類型值。

          lshl

           

          左移long類型值。

          ishr

           

          算術(shù)右移int類型值。

          lshr

           

          算術(shù)右移long類型值。

          iushr

           

          邏輯右移int類型值。

          lushr

           

          邏輯右移long類型值。

           

          邏輯運算——按位布爾運算

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          iand

           

          int類型按位與運算。

          land

           

          long類型的按位與運算。

          ior

           

          int類型的按位或運算。

          lor

           

          long類型的按位或運算。

          ixor

           

          int類型的按位異或運算。

          lxor

           

          long類型的按位異或運算。

           

          控制流指令——條件跳轉(zhuǎn)指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          ifeq

          branchbyte1

          branchbyte2

          若棧頂int類型值為0則跳轉(zhuǎn)。

          ifne

          branchbyte1

          branchbyte2

          若棧頂int類型值不為0則跳轉(zhuǎn)。

          iflt

          branchbyte1

          branchbyte2

          若棧頂int類型值小于0則跳轉(zhuǎn)。

          ifle

          branchbyte1

          branchbyte2

          若棧頂int類型值小于等于0則跳轉(zhuǎn)。

          ifgt

          branchbyte1

          branchbyte2

          若棧頂int類型值大于0則跳轉(zhuǎn)。

          ifge

          branchbyte1

          branchbyte2

          若棧頂int類型值大于等于0則跳轉(zhuǎn)。

          if_icmpeq

          branchbyte1

          branchbyte2

          若棧頂兩int類型值相等則跳轉(zhuǎn)。

          if_icmpne

          branchbyte1

          branchbyte2

          若棧頂兩int類型值不相等則跳轉(zhuǎn)。

          if_icmplt

          branchbyte1

          branchbyte2

          若棧頂兩int類型值前小于后則跳轉(zhuǎn)。

          if_icmple

          branchbyte1

          branchbyte2

          若棧頂兩int類型值前小于等于后則跳轉(zhuǎn)。

          if_icmpgt

          branchbyte1

          branchbyte2

          若棧頂兩int類型值前大于后則跳轉(zhuǎn)。

          if_icmpge

          branchbyte1

          branchbyte2

          若棧頂兩int類型值前大于等于后則跳轉(zhuǎn)。

          ifnull

          branchbyte1

          branchbyte2

          若棧頂引用值為null則跳轉(zhuǎn)。

          ifnonnull

          branchbyte1

          branchbyte2

          若棧頂引用值不為null則跳轉(zhuǎn)。

          if_acmpeq

          branchbyte1

          branchbyte2

          若棧頂兩引用類型值相等則跳轉(zhuǎn)。

          if_acmpne

          branchbyte1

          branchbyte2

          若棧頂兩引用類型值不相等則跳轉(zhuǎn)。

           

          控制流指令——比較指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          lcmp

           

          比較棧頂兩long類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧。

          fcmpl

           

          比較棧頂兩float類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧。

          fcmpg

           

          比較棧頂兩float類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧。

          dcmpl

           

          比較棧頂兩double類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧。

          dcmpg

           

          比較棧頂兩double類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧。

           

          控制流指令——無條件跳轉(zhuǎn)指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          goto

          branchbyte1

          branchbyte2

          無條件跳轉(zhuǎn)到指定位置。

          goto_w

          branchbyte1

          branchbyte2

          branchbyte3

          branchbyte4

          無條件跳轉(zhuǎn)到指定位置(寬索引)。

           

          控制流指令——表跳轉(zhuǎn)指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          tableswitch

          <0-3bytepad>

          defaultbyte1

          defaultbyte2

          defaultbyte3

          defaultbyte4

          lowbyte1

          lowbyte2

          lowbyte3

          lowbyte4

          highbyte1

          highbyte2

          highbyte3

          highbyte4

          jump offsets...

          通過索引訪問跳轉(zhuǎn)表,并跳轉(zhuǎn)。

          lookupswitch

          <0-3bytepad>

          defaultbyte1

          defaultbyte2

          defaultbyte3

          defaultbyte4

          npairs1

          npairs2

          npairs3

          npairs4

          match offsets

          通過鍵值訪問跳轉(zhuǎn)表,并跳轉(zhuǎn)。

           

          控制流指令——異常和finally

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          athrow

           

          拋出異常。

          jsr

          branchbyte1

          branchbyte2

          跳轉(zhuǎn)到子例程序。

          jsr_w

          branchbyte1

          branchbyte2

          branchbyte3

          branchbyte4

          跳轉(zhuǎn)到子例程序(寬索引)。

          (wide)ret

          indexbyte

          返回子例程序。

           

          對象操作指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          new

          indexbyte1

          indexbyte2

          創(chuàng)建新的對象實例。

          checkcast

          indexbyte1

          indexbyte

          類型強轉(zhuǎn)。

          instanceof

          indexbyte1

          indexbyte2

          判斷類型。

          getfield

          indexbyte1

          indexbyte2

          獲取對象字段的值。

          putfield

          indexbyte1

          indexbyte2

          給對象字段賦值。

          getstatic

          indexbyte1

          indexbyte2

          獲取靜態(tài)字段的值。

          putstatic

          indexbyte1

          indexbyte2

          給靜態(tài)字段賦值。

           

          數(shù)組操作指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          newarray

          atype

          創(chuàng)建type類型的數(shù)組。

          anewarray

          indexbyte1

          indexbyte2

          創(chuàng)建引用類型的數(shù)組。

          arraylength

           

          獲取一維數(shù)組的長度。

          multianewarray

          indexbyte1

          indexbyte2

          dimension

          創(chuàng)建dimension維度的數(shù)組。

           

          方法調(diào)用指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          invokespecial

          indexbyte1

          indexbyte2

          編譯時方法綁定調(diào)用方法。

          invokevirtual

          indexbyte1

          indexbyte2

          運行時方法綁定調(diào)用方法。

          invokestatic

          indexbyte1

          indexbyte2

          調(diào)用靜態(tài)方法。

          invokeinterface

          indexbyte1

          indexbyte2

          count

          0

          調(diào)用接口方法。

           

          方法返回指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          ireturn

           

          返回int類型值。

          lreturn

           

          返回long類型值。

          freturn

           

          返回float類型值。

          dreturn

           

          返回double類型值。

          areturn

           

          返回引用類型值。

          return

           

          void函數(shù)返回。

           

          線程同步指令

          操作碼(助記符)

          操作數(shù)

          描述(棧指操作數(shù)棧)

          monitorenter

           

          進入并獲得對象監(jiān)視器。

          monitorexit

           

          釋放并退出對象監(jiān)視器。

          參考《深入解析JVM》 2010年10月6日

          posted on 2011-09-13 00:03 DLevin 閱讀(6845) 評論(1)  編輯  收藏 所屬分類: 深入JVM

          FeedBack:
          # re: Java二進制指令代碼解析
          2011-09-13 09:04 | tb
          好東西 收藏了   回復(fù)  更多評論
            
          主站蜘蛛池模板: 长宁区| 无为县| 鹤山市| 巴彦淖尔市| 海阳市| 玛曲县| 东乌珠穆沁旗| 赤城县| 方城县| 黄龙县| 丰顺县| 尚志市| 广西| 松江区| 兖州市| 涿鹿县| 洪洞县| 奉节县| 砀山县| 陆丰市| 东山县| 吉木乃县| 任丘市| 礼泉县| 信宜市| 凤城市| 大同市| 枣庄市| 安国市| 汝城县| 贵州省| 沁水县| 兴义市| 商丘市| 龙陵县| 花莲市| 乌鲁木齐县| 慈溪市| 大宁县| 紫阳县| 云安县|