日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入理解JVM - 虚拟机字节码指令集

發布時間:2023/12/31 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解JVM - 虚拟机字节码指令集 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java虛擬機的指令由一個字節長度的、代表著某種特定操作含義的數字(稱為操作碼,Opcode)以及跟隨其后的零至多個代表此操作所需的參數(稱為操作數,Operand)構成。因為只有一個字節的長度,所以指令總數不能超過256個。

在Java虛擬機的指令集中,大多數指令都包含其操作所對應的數據類型信息,如:i代表對int類型的數據操作,l代表long,s代表short,b代表byte,c代表char,f代表float,d代表double,a代表reference。

解釋器的執行模型

Java虛擬機的解釋器的執行模型:

do {自動計算PC寄存器的值加1;根據PC寄存器指示的位置,從字節碼流中取出操作碼;if (字節碼存在操作數) 從字節碼流中取出操作數;執行操作碼所定義的操作; } while (字節碼流長度 > 0);

常量入棧指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0x01aconst_null將 null推送至棧頂
0x02iconst_m1將 -1(int)推送至棧頂
0x03iconst_0將 0(int)推送至棧頂
0x04iconst_1將 1(int)推送至棧頂
0x05iconst_2將 2(int)推送至棧頂
0x06iconst_3將 3(int)推送至棧頂
0x07iconst_4將 4(int)推送至棧頂
0x08iconst_5將 5(int)推送至棧頂
0x09lconst_0將 0(long)推送至棧頂
0x0alconst_1將 1(long)推送至棧頂
0x0bfconst_0將 0(float)推送至棧頂
0x0cfconst_1將 1(float)推送至棧頂
0x0dfconst_2將 2(float)推送至棧頂
0x0edconst_0將 0(double)推送至棧頂
0x0fdconst_1將 1(double)推送至棧頂
0x10bipushvaluebyte將一個byte值帶符號擴展成int推送至棧頂
0x11sipushvaluebyte1
valuebyte2
將一個short值帶符號擴展成int推送至棧頂
0x12ldcindexbyte1將int、float或String型常量值從常量池中推送至棧頂
0x13ldc_windexbyte1
indexbyte2
將int、float或String型常量值從常量池中推送至棧頂(寬索引)
0x14ldc2_windexbyte1
indexbyte2
將long或double型常量值從常量池中推送至棧頂(寬索引)

局部變量值轉載到棧中指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0x15iloadindexbyte從局部變量indexbyte中裝載int類型值推送至棧頂
0x16lloadindexbyte從局部變量indexbyte中裝載long類型值推送至棧頂
0x17floadindexbyte從局部變量indexbyte中裝載float類型值推送至棧頂
0x18dloadindexbyte從局部變量indexbyte中裝載double類型值推送至棧頂
0x19aloadindexbyte從局部變量indexbyte中裝載引用類型值推送至棧頂
0x1aiload_0將第1個int型本地變量推送至棧頂
0x1biload_1將第2個int型本地變量推送至棧頂
0x1ciload_2將第4個int型本地變量推送至棧頂
0x1diload_3將第4個int型本地變量推送至棧頂
0x1elload_0將第1個long型本地變量推送至棧頂
0x1flload_1將第2個long型本地變量推送至棧頂
0x20lload_2將第3個long型本地變量推送至棧頂
0x21lload_3將第4個long型本地變量推送至棧頂
0x22fload_0將第1個float型本地變量推送至棧頂
0x23fload_1將第2個float型本地變量推送至棧頂
0x24fload_2將第3個float型本地變量推送至棧頂
0x25fload_3將第4個float型本地變量推送至棧頂
0x26dload_0將第1個double型本地變量推送至棧頂
0x27dload_1將第2個double型本地變量推送至棧頂
0x28dload_2將第3個double型本地變量推送至棧頂
0x29dload_3將第4個double型本地變量推送至棧頂
0x2aaload_0將第1個引用類型本地變量推送至棧頂
0x2baload_1將第2個引用類型本地變量推送至棧頂
0x2caload_2將第3個引用類型本地變量推送至棧頂
0x2daload_3將第4個引用類型本地變量推送至棧頂
0x2eiaload將int類型數組的索引值推送至棧頂
0x2flaload將long類型數組的索引值推送至棧頂
0x30faload將float類型數組的索引值推送至棧頂
0x31daload將double類型數組的索引值推送至棧頂
0x32aaload將引用類型數組的索引值推送至棧頂
0x33baload將boolean或byte類型數組的索引值推送至棧頂(先轉換為int類型值,后壓棧)
0x34caload將char類型數組的索引值推送至棧頂(先轉換為int類型值,后壓棧)
0x35saload將short類型數組的索引值推送至棧頂(先轉換為int類型值,后壓棧)

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

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0x36(wide)istoreindexbyte將棧頂int類型值保存到局部變量indexbyte中
0x37(wide)lstoreindexbyte將棧頂long類型值保存到局部變量indexbyte中
0x38(wide)fstoreindexbyte將棧頂float類型值保存到局部變量indexbyte中
0x39(wide)dstoreindexbyte將棧頂double類型值保存到局部變量indexbyte中
0x3a(wide)astoreindexbyte將棧頂引用類型值保存到局部變量indexbyte中
0x3bistore_0將棧頂int類型值保存到局部變量0中
0x3cistore_1將棧頂int類型值保存到局部變量1中
0x3distore_2將棧頂int類型值保存到局部變量2中
0x3eistore_3將棧頂int類型值保存到局部變量3中
0x3flstore_0將棧頂long類型值保存到局部變量0中
0x40lstore_1將棧頂long類型值保存到局部變量1中
0x41lstore_2將棧頂long類型值保存到局部變量2中
0x42lstroe_3將棧頂long類型值保存到局部變量3中
0x43fstore_0將棧頂float類型值保存到局部變量0中
0x44fstore_1將棧頂float類型值保存到局部變量1中
0x45fstore_2將棧頂float類型值保存到局部變量2中
0x46fstore_3將棧頂float類型值保存到局部變量3中
0x47dstore_0將棧頂double類型值保存到局部變量0中
0x48dstore_1將棧頂double類型值保存到局部變量1中
0x49dstore_2將棧頂double類型值保存到局部變量2中
0x4adstore_3將棧頂double類型值保存到局部變量3中
0x4bastroe_0將棧頂引用類型值保存到局部變量0中
0x4castore_1將棧頂引用類型值保存到局部變量1中
0x4dastore_2將棧頂引用類型值保存到局部變量2中
0x4eastore_3將棧頂引用類型值保存到局部變量3中
0x4fiastore將棧頂int類型值保存到指定int類型數組的指定索引位
0x50lastore將棧頂long類型值保存到指定long類型數組的指定索引位
0x51fastore將棧頂float類型值保存到指定float類型數組的指定索引位
0x52dastore將棧頂double類型值保存到指定double類型數組的指定索引位
0x53aastore將棧頂引用類型值保存到指定引用類型數組的指定索引位
0x54bastroe將棧頂boolean類型值或byte類型值保存到指定boolean類型數組或byte類型數組的指定索引位
0x55castore將棧頂char類型值保存到指定char類型數組的指定索引位
0x56sastore將棧頂short類型值保存到指定short類型數組的指定索引位

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

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0x00nop空操作
0x57pop從棧頂彈出一個字長的數據(不是long和double)
0x58pop2從棧頂彈出兩個字長的數據(一個long或double,或者是兩個單字節長度數值)
0x59dup復制棧頂一個字長的數據,將復制后的數據壓入棧頂
0x5adup_x1復制棧頂一個字長的數據,彈出棧頂兩個字長數據,先將復制后的數據壓入棧頂,再將彈出的兩個字長數據壓入棧頂
0x5bdup_x2復制棧頂一個字長的數據,彈出棧頂三個字長的數據,將復制后的數據壓入棧頂,再將彈出的三個字長的數據壓入棧頂
0x5cdup2復制棧頂兩個字長的數據,將復制后的兩個字長的數據壓入棧頂
0x5ddup2_x1dup_x1 指令的雙倍版
0x5edup2_x2dup_x2 指令的雙倍版
0x5fswap將棧最頂端的兩個數值互換(數值不能是long或double)

整數和浮動點數運算

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0x60iadd將棧頂兩int類型數相加,并將結果壓入棧頂
0x61ladd將棧頂兩long類型數相加,并將結果壓入棧頂
0x62fadd將棧頂兩float類型數相加,并將結果壓入棧頂
0x63dadd將棧頂兩double類型數相加,并將結果壓入棧頂
0x64isub將棧頂兩int類型數相減,并將結果壓入棧頂
0x65lsub將棧頂兩long類型數相減,并將結果壓入棧頂
0x66fsub將棧頂兩float類型數相減,并將結果壓入棧頂
0x67dsub將棧頂兩double類型數相減,并將結果壓入棧頂
0x68imul將棧頂兩int類型數相乘,并將結果壓入棧頂
0x69lmul將棧頂兩long類型數相乘,并將結果壓入棧頂
0x6afmul將棧頂兩float類型數相乘,并將結果壓入棧頂
0x6bdmul將棧頂兩double類型數相乘,并將結果壓入棧頂
0x6cidiv將棧頂兩int類型數相除,并將結果壓入棧頂
0x6dldiv將棧頂兩long類型數相除,并將結果壓入棧頂
0x6efdiv將棧頂兩float類型數相除,并將結果壓入棧頂
0x6fddiv將棧頂兩double類型數相除,并將結果壓入棧頂
0x70irem將棧頂兩int類型數取模,并將結果壓入棧頂
0x71lrem將棧頂兩long類型數取模,并將結果壓入棧頂
0x72frem將棧頂兩float類型數取模,并將結果壓入棧頂
0x73drem將棧頂兩double類型數取模,并將結果壓入棧頂
0x74ineg將棧頂int類型值取負,并將結果壓入棧頂
0x75lneg將棧頂long類型值取負,并將結果壓入棧頂
0x76fneg將棧頂float類型值取反,并將結果壓入棧頂
0x77dneg將棧頂double類型值取負,并將結果壓入棧頂
0x84(wide)iincindexbyte
constbyte
將整數值constbyte加到indexbyte指定的int類型的局部變量中(i++,i–,i+=2;)

邏輯運算 - 移位運算

指令碼操作碼(助記符)操作數棧描述(棧指操作數棧)
0x78ishl… , a , n(a << n) 左移int類型值,并將結果壓入棧頂
0x79lshl… , a , n(a << n) 左移long類型值,并將結果壓入棧頂
0x7aishr… , a , n(a >> n) 算術右移int類型值,并將結果壓入棧頂
0x7blshr… , a , n(a >> n) 算術右移long類型值,并將結果壓入棧頂
0x7ciushr… , a , n(a >>> n) 邏輯右移int類型值,并將結果壓入棧頂
0x7dlushr… , a , n(a >>> n) 邏輯右移long類型值,并將結果壓入棧頂

邏輯運算 - 位運算

指令碼操作碼(助記符)操作數棧描述(棧指操作數棧)
0x7eiand… , a , n(a & b) 對int類型按位與運算,并將結果壓入棧頂
0x7fland… , a , n(a & b) 對long類型的按位與運算,并將結果壓入棧頂
0x80ior… , a , n(a | b) 對int類型的按位或運算,并將結果壓入棧頂
0x81lor… , a , n(a | b) 對long類型的按位或運算,并將結果壓入棧頂
0x82ixor… , a , n(a ^ b) 對int類型的按位異或運算,并將結果壓入棧頂
0x83lxor… , a , n(a ^ b) 對long類型的按位異或運算,并將結果壓入棧頂

類型轉換指令

指令碼操作碼(助記符)操作數棧描述(棧指操作數棧)
0x85i2l… , a(long) a, 將棧頂int類型值轉換為long類型值,并將結果壓入棧頂
0x86i2f… , a(float) a, 將棧頂int類型值轉換為float類型值,并將結果壓入棧頂
0x87i2d… , a(double) a, 將棧頂int類型值轉換為double類型值,并將結果壓入棧頂
0x88l2i… , a(int) a, 將棧頂long類型值轉換為int類型值,并將結果壓入棧頂
0x89l2f… , a(float) a, 將棧頂long類型值轉換為float類型值,并將結果壓入棧頂
0x8al2d… , a(double) a, 將棧頂long類型值轉換double類型值,并將結果壓入棧頂
0x8bf2i… , a(int) a, 將棧頂float類型值轉換為int類型值,并將結果壓入棧頂
0x8cf2l… , a(long) a, 將棧頂float類型值轉換為long類型值,并將結果壓入棧頂
0x8df2d… , a(double) a, 將棧頂float類型值轉換為double類型值,并將結果壓入棧頂
0x8ed2i… , i(double) a, 將棧頂double類型值轉換為int類型值,并將結果壓入棧頂
0x8fd2l… , a(long) a, 將棧頂double類型值轉換為long類型值,并將結果壓入棧頂
0x90d2f… , a(float) a, 將棧頂double類型值轉換為float類型值,并將結果壓入棧頂
0x91i2b… , a(byte) a, 將棧頂int類型值截斷成byte類型,后帶符號擴展成int類型值壓入棧頂
0x92i2c… , a(char) a, 將棧頂int類型值截斷成char類型值,后帶符號擴展成int類型值壓入棧頂
0x93i2s… , a(short) a, 將棧頂int類型值截斷成short類型值,后帶符號擴展成int類型值壓入棧頂

控制流指令 - 比較指令

指令碼操作碼(助記符)操作數棧描述(棧指操作數棧)
0x94lcmp… , a , b比較棧頂兩long類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧 [a == b ? 0 : (a < b ? -1 : 1)]
0x95fcmpl… , a , b比較棧頂兩float類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧 [a == b ? 0 : (a < b ? -1 : 1)]
0x96fcmpg… , a , b比較棧頂兩float類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧 [a == b ? 0 : (a < b ? -1 : 1)]
0x97dcmpl… , a , b比較棧頂兩double類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧 [a == b ? 0 : (a < b ? -1 : 1)]
0x98dcmpg… , a , b比較棧頂兩double類型值,前者大,1入棧;相等,0入棧;后者大,-1入棧;有NaN存在,-1入棧 [a == b ? 0 : (a < b ? -1 : 1)]

控制流指令 - 條件跳轉指令

指令碼操作碼(助記符)棧操作之前棧操作之后描述(棧指操作數棧)
0x99ifeq… , i若棧頂int類型值為0則跳轉 (jump if i == 0)
0x9aifne… , i若棧頂int類型值不為0則跳轉 (jump if i != 0)
0x9biflt… , i若棧頂int類型值小于0則跳轉 (jump if i < 0)
0x9cifge… , i若棧頂int類型值大于等于0則跳轉 (jump if i >= 0)
0x9difgt… , i若棧頂int類型值大于0則跳轉 (jump if i > 0)
0x9eifle… , i若棧頂int類型值小于等于0則跳轉 (jump if i <= 0)
0x9fif_icmpeq… , i , j若棧頂兩int類型值相等則跳轉 (jump if i == j)
0xa0if_icmpne… , i , j若棧頂兩int類型值不相等則跳轉 (jump if i != j)
0xa1if_icmplt… , i , j若棧頂兩int類型值前小于后則跳轉 (jump if i < j)
0xa4if_icmple… , i , j若棧頂兩int類型值前小于等于后則跳轉 (jump if i <= j)
0xa3if_icmpgt… , i , j若棧頂兩int類型值前大于后則跳轉 (jump if i > j)
0xa2if_icmpge… , i , j若棧頂兩int類型值前大于等于后則跳轉 (jump if i >= j)
0xa5if_acmpeq… , o , p若棧頂兩引用類型值相等則跳轉 (jump if o == p)
0xa6if_acmpne… , o , p若棧頂兩引用類型值不相等則跳轉 (jump if o != p)
0xc6ifnull… , o若棧頂引用值為null則跳轉 (jump if o == null)
0xc7ifnonnull… , o若棧頂引用值不為null則跳轉 (jump if o != null)

控制流指令 - 無條件跳轉指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0xa7gotobranchbyte1
branchbyte2
無條件跳轉到指定位置
0xc8goto_wbranchbyte1
branchbyte2
branchbyte3
branchbyte4
無條件跳轉到指定位置(寬索引)

控制流指令 - 表跳轉指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0xaatableswitch<0 - 3bytepad>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
lowbyte1
lowbyte2
lowbyte3
lowbyte4
highbyte1
highbyte2
highbyte3
highbyte4
jump offsets…
通過索引訪問跳轉表,并跳轉
jump always
0xablookupswitch<0 - 3bytepad>
defaultbyte1
defaultbyte2
defaultbyte3
defaultbyte4
npairs1
npairs2
npairs3
npairs4
match offsets
通過鍵值訪問跳轉表,并跳轉
jump always

控制流指令 - 異常和finally

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0xbfathrow拋出異常
0xa8jsrbranchbyte1
branchbyte2
跳轉到子例程序
0xc9jsr_wbranchbyte1
branchbyte2
branchbyte3
branchbyte4
跳轉到子例程序(寬索引)
0xa9(wide)retindexbyte返回子例程序

對象操作指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0xbbnewindexbyte1
indexbyte2
創建新的對象實例,并將其引用壓入棧頂
0xc0checkcastindexbyte1
indexbyte
類型強轉,如果該檢查未通過將會拋出ClassCastException異常
0xc1instanceofindexbyte1
indexbyte2
檢查對象是否是指定的類的實例。如果是,1進棧;否則,0進棧
0xb2getstaticindexbyte1
indexbyte2
獲取靜態字段的值,并將其引用壓入棧頂
0xb3putstaticindexbyte1
indexbyte2
給靜態字段賦值
0xb4getfieldindexbyte1
indexbyte2
獲取對象字段的值,并將其引用壓入棧頂
0xb5putfieldindexbyte1
indexbyte2
給對象字段賦值

數組操作指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0xbcnewarrayatype創建type類型的數組
0xbdanewarrayindexbyte1
indexbyte2
創建引用類型的數組
0xbearraylength獲取一維數組的長度
0xc5multianewarrayindexbyte1
indexbyte2
dimension
創建dimension維度的數組

方法調用指令

指令碼操作碼(助記符)操作數描述(棧指操作數棧)
0xb7invokespecialindexbyte1
indexbyte2
編譯時方法綁定調用方法
0xb6invokevirtualindexbyte1
indexbyte2
運行時方法綁定調用方法
0xb8invokestaticindexbyte1
indexbyte2
調用靜態方法
0xb9invokeinterfaceindexbyte1
indexbyte2
count
0
調用接口方法

方法返回指令

指令碼操作碼(助記符)描述(棧指操作數棧)
0xacireturn返回int類型值
0xadlreturn返回long類型值
0xaefreturn返回float類型值
0xafdreturn返回double類型值
0xb0areturn返回引用類型值
0xb1returnvoid函數返回

線程同步指令

指令碼操作碼(助記符)描述(棧指操作數棧)
0xc2monitorenter進入并獲得對象監視器,獲取對象鎖,用于同步方法或者同步塊
0xc3monitorexit釋放并退出對象監視器,釋放對象鎖,用于同步方法或者同步塊

wide指令

指令碼操作碼(助記符)描述(棧指操作數棧)
0xc4wide使用附加字節擴展局部變量的寬度(iinc指令特殊)

示例

方法的執行示例

Java源碼:

public int inc() {int x;try {x = 1;return x;} catch (Exception e) {x = 2;return x;} finally {x = 3;} }

編譯后的ByteCode字節碼及異常表:

public int inc();Code:Stack=1, Locals=5, Args_size=10: iconst_1 // try塊中的x=11: istore_12: iload_1 // 保存x到returnValue中,此時x=13: istore 45: iconst_3 // finaly塊中的x=36: istore_17: iload 4 // 將returnValue中的值放到棧頂,準備給ireturn返回9: ireturn10: astore_2 // 給catch中定義的Exception e賦值,存儲在變量槽 2中11: iconst_2 // catch塊中的x=212: istore_113: iload_1 // 保存x到returnValue中,此時x=214: istore 416: iconst_3 // finaly塊中的x=317: istore_118: iload 4 // 將returnValue中的值放到棧頂,準備給ireturn返回20: ireturn21: astore_3 // 如果出現了不屬于java.lang.Exception及其子類的異常才會走到這里22: iconst_3 // finaly塊中的x=323: istore_124: aload_3 // 將異常放置到棧頂,并拋出25: athrowException table:from to target type0 5 10 Class java/lang/Exception0 5 21 any10 16 21 any

編譯器為這段Java源碼生成了三條異常表記錄,對應三條可能出現的代碼執行路徑。從Java代碼的語義上講,這三條執行路徑分別為:

  • 如果try語句塊中出現屬于Exception或其子類的異常,轉到catch語句塊處理;
  • 如果try語句塊中出現不屬于Exception或其子類的異常,轉到finally語句塊處理;
  • 如果catch語句塊中出現任何異常,轉到finally語句塊處理。

參考

《深入理解JAVA虛擬機》

https://www.cnblogs.com/honger/p/6815198.html

總結

以上是生活随笔為你收集整理的深入理解JVM - 虚拟机字节码指令集的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。