do{ 自動計算pc寄存器以及從pc寄存器的位置取出操做碼; if(存在操做數){ 取出操做數; } 執行操做碼所定義的操做; }while(處理下一次循環);
byte | short | int | long | float | double | char | reference | boolean |
b | s | i | l | f | d | c | a | 無 |
加載存儲指令 |
算數指令 |
類型轉換指令 |
對象的建立於操做 |
操做數棧管理指令 |
控制轉移指令 |
方法調用和返回指令 |
拋出異常 |
同步 |
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 |
另外須要格外注意的是,上表是爲了呈現部分與數據類型相關聯的操做碼
並非說全部的操做碼都在上表中,僅僅是和數據類型相關聯的纔出如今了上表中
|
實際類型 | 運算類型 | 分類 |
boolean | int | 1 |
int | int | 1 |
byte | int | 1 |
short | int | 1 |
int | int | 1 |
float | float | 1 |
reference | reference | 1 |
returnAddress | returnAddress | 1 |
long | long | 2 |
double | double | 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
|
再次強調 加add 減sub 乘mul 除div 求餘rem 取反neg 移位sh l r表示左右 與and 或or 異或xor 自增inc cmp比較 |
加 減 乘 除 求餘 取反 支持 <int i long l float f double d> 四種類型 理解點:經常使用操做支持四種經常使用類型 byte short char boolean使用int 移位運算與按位與或異或運算 支持< int i long l > 理解點: 移位與位運算支持整型,byte short char boolean使用int 另外還有long 自增支持< int i > |
補充說明:
關於移位運算,
左移只有一種:
規則:丟棄最高位,往左移位,右邊空出來的位置補0
右移有兩種:
1. 邏輯右移:丟棄最低位,向右移位,左邊空出來的位置補0
2. 算術右移:丟棄最低位,向右移位,左邊空出來的位置補原來的符號位(即補最高位)
移位運算的u表示的正是邏輯移位d 和f開頭 分別表明double 和float的比較 cmpg 與cmpl 的惟一區別在於對NaN的處理,更多詳細內容能夠查看虛擬機規範的相關指令 lcmp 比較long類型的值 |
類型轉換指令能夠將兩種不一樣的數值類型進行相互轉換。
這些轉換操做通常用於實現用戶代碼中的顯式類型轉換操做
或者用來解決字節碼指令集不完備的問題
由於數據類型相關指令沒法與數據類型一一對應的問題,好比byte short char boolean使用int, 因此必需要轉換
|
分爲寬化 和 窄化 含義如字面含義,存儲長度的變寬或者變窄 寬化也就是常說的安全轉換,不會由於超過目標類型最大值丟失信息 窄化則意味着極可能會丟失信息 寬化指令和窄化指令的形式爲 操做類型 2 (to) 目標類型 好比 i2l int 轉換爲long |
寬化指令
int類型到long、float或者double類型
long類型到float、double類型
float類型到double類型
i2l、i2f、i2d
l2f 、l2d
f2d
|
窄化指令 int類型到byte short char類型 long類型到int類型 float類型到int或者long類型 從double類型到int long 或者float類型 i2b 、i2s 、i2c l2i f2i 、f2l d2i 、d2l 、d2f |
實例和數組都是對象 可是Java虛擬機對類實例和數組的建立使用了不一樣的字節碼指令 |
涉及到對象的建立與訪問的相關操做有: 1.建立實例對象/數組 2.訪問實例變量和類變量 3.加載與存儲,對於類實例屬於引用類型存取使用加載存儲指令,因此此處只有數組有相關操做了 4.還有一些附屬信息 數組長度以及檢查類實例或者數組類型 |
建立類實例 : new 建立數組的指令 : newarray 分配數據成員類型爲基本數據類型的新數組 anewarray 分配數據成員類型爲引用類型的新數組 multianewarray 分配新的多維數組 |
類變量聲明的時候使用static關鍵字 訪問與存儲類中的靜態字段也是使用static關鍵字 getstatic 從類中獲取靜態字段 putstatic 設置類中靜態字段的值 普通的成員實例變量使用field指代 getfield 從對象中獲取字段值 putfield 設置對象中的字段的值 |
訪問與存儲以前介紹過 使用的load 和store 數組也是對象 引用使用a來表示 因此對於數組的存取和訪問指令 使用 類型+a+load 或者store 的形式 把一個數組元素加載到操做數棧的指令: byte char short int long float double reference 對應的指令分別是 baload caload saload iaload laload faload daload aaload 把一個操做數棧的值存儲到數組元素中的指令:
byte char short int long float double reference
對應的指令分別是:
bastore castore sastore iastore lastore fastore dastore aastore
|
獲取數組長度的指令 arraylength 檢查類實例或者數組類型的指令 instanceof checkcast |
控制轉移指令可讓Java虛擬機有條件或者無條件的從指定的位置指令繼續執行程序 而不是當前控制轉移指令的下一條 |
控制轉移指令包括
條件轉移 複合條件轉移以及無條件轉移
boolean byte short char都是使用int類型的比較指令
long float double 類型的條件分支比較,會先執行相應的比較運算指令,運算指令會返回一個整型數值到操做數棧中
隨後在執行int類型的條件分支比較操做來完成整個分支跳轉
顯然,虛擬機會對int類型的支持最爲豐富
全部的int類型的條件分支指令進行的都是有符號的比較
|
long float double 類型的比較指令 lcmp fcmpl fcmpg dcmpl dcmpg 這五個都比較棧頂上面兩個 指定類型的元素,而後將結果 [-1 0 1] 壓入棧頂 cmpl與cmpg區別在於對NaN的處理,有興趣的能夠查看Java虛擬機規範 |
條件跳轉指令
接下來這六個也就是上面說的配合long float 和double類型條件分支的比較
他們會對當前棧頂元素進行操做判斷,只有棧頂的一個元素做爲操做數
ifeq 當棧頂int類型元素 等於0時 ,跳轉
ifne 當棧頂int類型元素 不等於0 時,跳轉
iflt 當棧頂int類型元素 小於0 時,跳轉
ifle 當棧頂int類型元素 小於等於0 時,跳轉
ifgt 當棧頂int類型元素 大於0 時,跳轉
ifge 當棧頂int類型元素 大於等於0 時,跳轉
|
相似上面的long float double
int類型 和 reference 固然也有對兩個操做數的比較指令,並且還一步到位了
if_icmpeq 比較棧頂兩個int類型數值的大小 ,當前者 等於 後者時,跳轉
if_icmpne 比較棧頂兩個int類型數值的大小 ,當前者 不等於 後者時,跳轉
if_icmplt 比較棧頂兩個int類型數值的大小 ,當前者 小於 後者時,跳轉
if_icmple 比較棧頂兩個int類型數值的大小 ,當前者 小於等於 後者時,跳轉
if_icmpge 比較棧頂兩個int類型數值的大小 ,當前者 大於等於 後者時,跳轉
if_icmpgt 比較棧頂兩個int類型數值的大小 ,當前者 大於 後者時,跳轉
if_acmpeq 比較棧頂兩個引用類型數值的大小 ,當前者 等於 後者時,跳轉
if_acmpne 比較棧頂兩個引用類型數值的大小 ,當前者 不等於 後者時,跳轉
|
複合條件跳轉指令 tableswitch switch 條件跳轉 case值連續 lookupswitch switch 條件跳轉 case值不連續 |
無條件轉移指令 goto 無條件跳轉 goto_w 無條件跳轉 寬索引 jsr SE6以前 finally字句使用 跳轉到指定16位的offset,並將jsr下一條指令地址壓入棧頂 jsr_w SE6以前 同上 寬索引 ret SE6以前返回由指定的局部變量所給出的指令地址(通常配合jsr jsr_w使用) w同局部變量的寬索引含義 |
方法調用和方法返回指令 |
方法調用分爲
實例方法接口方法 調用父類私有實力初始化等特殊方法,類靜態方法等
如下5條指令用於方法調用:
invokevirtual指令用於調用對象的實例方法
invokeinterface指令用於調用接口方法,它會在運行時搜索由特定對象所實現的這個接口方法,並找出適合的方法進行調用。
invokespecial指令用於調用一些須要特殊處理的實例方法,包括實例初始化方法、私有方法和父類方法。
invokestatic指令用於調用類方法(static方法)
invokedynamic 調用動態連接方法 比較複雜,稍後有時間會專門講解
|
方法的調用與數據類型無關 可是方法的返回指令根據返回值類型進行區分 ireturn boolean byte char short int類型使用 lreturn long freturn float dreturn double areturn reference return void方法 實例初始化方法(構造方法) 類和接口的類初始化方法 |
異常處理指令 |
Java程序中顯式拋出異常的操做 throw語句,都是由athrow 指令來實現的 除了throw語句顯式的拋出異常狀況以外,Java虛擬機規範還規定了許多運行時異常 會在其餘Java虛擬機指令檢測到異常狀況時,自動拋出 |
同步指令 |
同步一段指令集序列一般是由Java語言中的synchronized 語句塊來表示的, Java虛擬機的指令集中有monitorenter monitorexit (monitor +enter/exit) |