位元組碼指令集是瞭解學習虛擬機運行的必須步驟,本文詳細的介紹了絕大多數的位元組碼指令,從多個維度對位元組碼指令進行瞭解析說明,並且對位元組碼指令集助記符進行了更加詳細的釋義. 本文主要涉及jvm的位元組碼指令集 助記符 位元組碼邏輯功能分類 以及用法 ...
說明,本文的目的在於從巨集觀邏輯上介紹清楚絕大多數的位元組碼指令的含義以及分類 只要認真閱讀本文必然能夠對位元組碼指令集有所瞭解 如果需要瞭解清楚每一個指令的具體詳盡用法,請參閱虛擬機規範
指令簡介
電腦指令就是指揮機器工作的指示和命令,程式就是一系列按一定順序排列的指令,執行程式的過程就是電腦的工作過程。 通常一條指令包括兩方面的內容: 操作碼和操作數,操作碼決定要完成的操作,操作數指參加運算的數據及其所在的單元地址。 虛擬機的位元組碼指令亦是如此含義 class文件相當於JVM的機器語言 class文件是源代碼信息的完整表述 方法內的代碼被保存到code屬性中,位元組碼指令序列就是方法的調用過程 Java虛擬機的指令由一個位元組長度的、代表著某種特定操作含義的操作碼(opcode) 以及跟隨其後的零至多個代表此操作所需參數的操作數(operand)所構成 虛擬機中許多指令並不包含操作數.只有一個操作碼。 如果忽略異常處理,執行邏輯類似do{ 自動計算pc寄存器以及從pc寄存器的位置取出操作碼; if(存在操作數){ 取出操作數; } 執行操作碼所定義的操作; }while(處理下一次迴圈);操作數的數量以及長度取決於操作碼,如果一個操作數的長度超過了一個位元組,那麼它將大端排序存儲,即高位在前的位元組序。 例如,如果要將一個16位長度的無符號整數使用兩個無符號位元組存儲起來(將它們命名為byte]和byte2 ) 那這個16位無符號整數的值就是: (bytel<<8) | byte2. 位元組碼指令流應當都是單位元組對齊的,只有,tableswitch和lookupswitch兩個指令例外 這倆貨是4位元組為單位的 限制了操作碼長度為一個位元組 0~255, 但是也就導致操作碼個數不能超過256 放棄編譯後代碼的操作數對齊 也就省略很多填充和間隔符號 限制長度和放棄對齊也儘可能的讓編譯後的代碼短小精幹 但是如果向上面那樣如果操作碼處理超過一個位元組的數據時,就必須在運行時從位元組流中重建出具體數據結構,將會有一定程度的性能損失
指令詳解
說明: 操作碼一個位元組長度,也就是8位二進位數字,也就是兩位十六進位數字 class文件只會出現數字形式的操作碼 但是為了便於人識別,操作碼有他對應的助記符形式 接下來所有的指令的說明,都是以助記符形式表達的 但是要明確,實際的執行運行並不存在助記符這些東西,都是根據操作碼的值來執行 指令本身就是為了功能邏輯運算 運算自然要處理數據 所以說指令的設計是邏輯功能點與數據類型的結合 接下來先看下有哪些數據類型和邏輯功能點數據類型
上一篇文章中已經說明JVM支持的數據類型 共有9中基本類型 對於基本類型 指令在設計的時候都用一個字母縮寫來指代(boolean除外)byte | short | int | long | float | double | char | reference | boolean |
b | s | i | l | f | d | c | a | 無 |
邏輯功能
載入存儲指令 |
算數指令 |
類型轉換指令 |
對象的創建於操作 |
操作數棧管理指令 |
控制轉移指令 |
方法調用和返回指令 |
拋出異常 |
同步 |
另外還有一些,比如無條件跳轉指令goto 則是與數據類型無關的 接下來將會從各個維度對絕大多數指令進行介紹 註意: 在不同的分類中,有些指令是重覆的,因為有很多操作是需要處理數據的 也就是說數據類型相關的指令裡面可能跟很多邏輯功能點相關聯,比如 載入存儲指令,可以載入int 可以載入long等 他在我接下來的說明中,可能不僅僅會出現在數據類型相關的指令中 也會出現在載入存儲指令的介紹中,請不要疑惑 就是要從多維度介紹這些指令,才能更好地理解他們
指令-相關電腦英語辭彙含義
push | push | 按 推動 壓入 |
load | load | 載入 裝載 |
const | const | 常數,不變的 |
store | store | 存儲 保存到 |
add | add | 加法 |
sub | subduction | 減法 |
mul | multiplication | 乘法 |
div | division | 除法 |
inc | increase | 增加 |
rem | remainder | 取餘 剩下的留下的 |
neg | negate | 取反 否定 |
sh | shift | 移位 移動變換 |
and | and | 與 |
or | or | 或 |
xor | exclusive OR | 異或 |
2 | to | 轉換 轉變 變成 |
cmp | compare | 比較 |
return | return | 返回 |
eq | equal | 相等 |
ne | not equal | 不相等 |
lt | less than | 小於 |
le | less than or equal | 小於等於 |
gt | greater than | 大於 |
ge | greater than or equal | 大於等於 |
if | if | 條件判斷 如果 |
goto | goto | 跳轉 |
invoke | invoke | 調用 |
dup | dump | 複製 拷貝 卸下 丟下 |
指令-數據類型相關的指令
java中的操作碼長度只有個位元組,所以必然,並不會所有的類型都有對應的操作 Java虛擬機指令集對於特定的操作只提供了有限的類型相關指令 有一些單獨的指令可以再必要的時候用來將一些不支持的類型轉換為可支持的類型 |
操作碼/類型 | byte | short | int | long | float | double | char | reference |
Tipush | bipush | sipush | ||||||
Tconst | iconst | lconst | fconst | dconst | aconst | |||
Tload | iload | lload | fload | dload | aload | |||
Tstore | istore | lstore | fstore | dstore | astore | |||
Tinc | iinc | |||||||
Taload | baload | saload | iaload | laload | faload | daload | caload | aaload |
Tastore | bastore | sastore | iastore | lastore | fastore | dastore | castore | aastore |
Tadd | iadd | ladd | fadd | dadd | ||||
Tsub | isub | lsub | fsub | dsub | ||||
Tmul | imul | lmul | fmul | dmul | ||||
Tdiv | idiv | ldiv | fdiv | ddiv | ||||
Trem | irem | lrem | frem | drem | ||||
Tneg | ineg | lneg | fneg | dneg | ||||
Tshl | ishl | lshl | ||||||
Tshr | ishr | lshr | ||||||
Tushr | iushr | lushr | ||||||
Tand | iand | land | ||||||
Tor | ior | lor | ||||||
Txor | ixor | lxor | ||||||
i2T | i2b | i2s | i2l | i2f | i2d | |||
l2T | l2i | l2f | l2d | |||||
f2T | f2i | f2l | f2d | |||||
d2T | d2i | d2l | d2f | |||||
Tcmp | lcmp | |||||||
Tcmpl | fcmpl | dcmpl | ||||||
Tcmpg | fcmpg | dcmpg | ||||||
if_TcmpOP | if_icmpOP | if_acmpOP | ||||||
Treturn | ireturn | lreturn | freturn | dreturn | areturn |
另外需要格外註意的是,上表是為了呈現部分與數據類型相關聯的操作碼 並不是說所有的操作碼都在上表中,僅僅是和數據類型相關聯的才出現在了上表中 |