jvm 指令

任何一臺(tái)計(jì)算機(jī)的指令系統(tǒng)一般都包含有幾十條到上百條指令,下面按一般計(jì)算機(jī)的功能把指令劃分以下幾種類型.
(1)算術(shù)運(yùn)算指令
計(jì)算機(jī)指令系統(tǒng)一般都設(shè)有二進(jìn)制數(shù)加\減\比較和求補(bǔ)等最基本的指令,此外還設(shè)置了乘\除法運(yùn)算指令\浮點(diǎn)運(yùn)算指令以有十進(jìn)制動(dòng)算指令等.
(2)邏輯運(yùn)算指令
一般計(jì)算機(jī)都具有與\或\非(求反)\異或(按位加)和測(cè)試等邏輯運(yùn)算指令.
(3)數(shù)據(jù)傳送指令.
這是一種常用的指令,用以實(shí)現(xiàn)寄存器與寄存器,寄存器與存儲(chǔ)單元以及存儲(chǔ)器單元與存儲(chǔ)器單元之間的數(shù)據(jù)傳送,對(duì)于存儲(chǔ)器來說,數(shù)據(jù)傳送包括對(duì)數(shù)據(jù)的讀(相當(dāng)于取數(shù)指令)和寫(相當(dāng)于存數(shù)指令)操作.
(4)移位操作指令
移位操作指令分為算術(shù)移位\邏輯移位和循環(huán)移位三種,可以實(shí)現(xiàn)對(duì)操作數(shù)左移或右移一位或若干位.
(5)堆棧及堆棧操作指令.
堆棧是由若干個(gè)連續(xù)存儲(chǔ)單元組成的先進(jìn)后出(FILO)存儲(chǔ)區(qū),第一個(gè)送入堆棧中的數(shù)據(jù)存放在棧底,最后送入堆棧中的數(shù)據(jù)存放在棧頂.棧底是固定不變的,而棧頂卻是隨著數(shù)據(jù)的入棧和出棧在不斷變化.
(6)字符串處理指令.
字符串處理指令就是一種非數(shù)值處理指令,一般包括字符串傳送,字符串轉(zhuǎn)換(把一種編碼的字符串轉(zhuǎn)換成另一種編碼的字符串),字符串比較,字符串查找(查找字符串中某一子串),字符串匹配,字符串的抽取(提取某一子串)和替換(把某一字符串用另一字符串替換)等.
(7)輸入輸出(I/O)指令.
計(jì)算機(jī)本身公是數(shù)據(jù)處理和管理機(jī)構(gòu),不能產(chǎn)生原始數(shù)把,也不能長期保存數(shù)據(jù).所處理的一切原始數(shù)據(jù)均來自輸入設(shè)備,所得的處理結(jié)果必須通過外總設(shè)備輸出.
(8)其它指令.
特權(quán)指令----具有特殊權(quán)限的指令,在多服務(wù)用戶\多任務(wù)的計(jì)算機(jī)系統(tǒng)中,特權(quán)指令是不可少的.
陷阱與陷阱指令---陷阱實(shí)際上是一種意外事故中斷,中斷的目的不是為請(qǐng)求CPU的正常處理,面是為了通知CPU所出現(xiàn)的故障,并根據(jù)故障情況,轉(zhuǎn)入相就的故障處理程序.
轉(zhuǎn)移指令---用來控制程序的執(zhí)行方向,實(shí)現(xiàn)程序的分支.
子程序調(diào)用指令---在騙寫程序過程中,常常需要編寫一些經(jīng)常使用的\能夠獨(dú)立完成的某一特定功能的程序段,在需要時(shí)能隨時(shí)調(diào)用,而不必重復(fù)編寫,以便節(jié)省存儲(chǔ)空間和簡(jiǎn)化程序設(shè)計(jì).

https://www.cnblogs.com/jentleTao/p/12699894.html

image.png
image.png

《JVM指令助記符》

變量到操作數(shù)棧:iload,iload_,lload,lload_,fload,fload_,dload,dload_,aload,aload_

操作數(shù)棧到變量:istore,istore_,lstore,lstore_,fstore,fstore_,dstore,dstor_,astore,astore_

常數(shù)到操作數(shù)棧:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_,lconst_,fconst_,dconst_

加:iadd,ladd,fadd,dadd

減:isub,lsub,fsub,dsub

乘:imul,lmul,fmul,dmul

除:idiv,ldiv,fdiv,ddiv

余數(shù):irem,lrem,frem,drem

取負(fù):ineg,lneg,fneg,dneg

移位:ishl,lshr,iushr,lshl,lshr,lushr

按位或:ior,lor

按位與:iand,land

按位異或:ixor,lxor

類型轉(zhuǎn)換:i2l,i2f,i2d,l2f,l2d,f2d(放寬數(shù)值轉(zhuǎn)換)
i2b,i2c,i2s,l2i,f2i,f2l,d2i,d2l,d2f(縮窄數(shù)值轉(zhuǎn)換)

創(chuàng)建類實(shí)例:new

創(chuàng)建新數(shù)組:newarray,anewarray,multianwarray

訪問類的域和類實(shí)例域:getfield,putfield,getstatic,putstatic

把數(shù)據(jù)裝載到操作數(shù)棧:baload,caload,saload,iaload,laload,faload,daload,aaload

從操作數(shù)棧存存儲(chǔ)到數(shù)組:bastore,castore,sastore,iastore,lastore,fastore,dastore,aastore

獲取數(shù)組長度:arraylength

檢相類實(shí)例或數(shù)組屬性:instanceof,checkcast

操作數(shù)棧管理:pop,pop2,dup,dup2,dup_xl,dup2_xl,dup_x2,dup2_x2,swap

有條件轉(zhuǎn)移:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnonnull,if_icmpeq,if_icmpene,
if_icmplt,if_icmpgt,if_icmple,if_icmpge,if_acmpeq,if_acmpne,lcmp,fcmpl
fcmpg,dcmpl,dcmpg

復(fù)合條件轉(zhuǎn)移:tableswitch,lookupswitch

無條件轉(zhuǎn)移:goto,goto_w,jsr,jsr_w,ret

調(diào)度對(duì)象的實(shí)例方法:invokevirtual

調(diào)用由接口實(shí)現(xiàn)的方法:invokeinterface

調(diào)用需要特殊處理的實(shí)例方法:invokespecial

調(diào)用命名類中的靜態(tài)方法:invokestatic

方法返回:ireturn,lreturn,freturn,dreturn,areturn,return

異常:athrow
finally關(guān)鍵字的實(shí)現(xiàn)使用:jsr,jsr_w,ret

《JVM指令集》

1、棧和局部變量操作

1.1  將常量壓入棧的指令     19

aconst_null 將null對(duì)象引用壓入棧
iconst_m1 將int類型常量-1壓入棧
iconst_0 將int類型常量0壓入棧
iconst_1 將int類型常量1壓入棧
iconst_2 將int類型常量2壓入棧
iconst_3 將int類型常量3壓入棧
iconst_4 將int類型常量4壓入棧
iconst_5 將int類型常量5壓入棧
lconst_0 將long類型常量0壓入棧
lconst_1 將long類型常量1壓入棧
fconst_0 將float類型常量0壓入棧
fconst_1 將float類型常量1壓入棧
dconst_0 將double類型常量0壓入棧
dconst_1 將double類型常量1壓入棧
bipush 將一個(gè)8位帶符號(hào)整數(shù)壓入棧
sipush 將16位帶符號(hào)整數(shù)壓入棧
ldc 把常量池中的項(xiàng)壓入棧
ldc_w 把常量池中的項(xiàng)壓入棧(使用寬索引)
ldc2_w 把常量池中l(wèi)ong類型或者double類型的項(xiàng)壓入棧(使用寬索引)
   1.2  從棧中的局部變量中裝載值的指令 33

iload 從局部變量中裝載int類型值
lload 從局部變量中裝載long類型值
fload 從局部變量中裝載float類型值
dload 從局部變量中裝載double類型值
aload 從局部變量中裝載引用類型值(refernce)
iload_0 從局部變量0中裝載int類型值
iload_1 從局部變量1中裝載int類型值
iload_2 從局部變量2中裝載int類型值
iload_3 從局部變量3中裝載int類型值
lload_0 從局部變量0中裝載long類型值
lload_1 從局部變量1中裝載long類型值
lload_2 從局部變量2中裝載long類型值
lload_3 從局部變量3中裝載long類型值
fload_0 從局部變量0中裝載float類型值
fload_1 從局部變量1中裝載float類型值
fload_2 從局部變量2中裝載float類型值
fload_3 從局部變量3中裝載float類型值
dload_0 從局部變量0中裝載double類型值
dload_1 從局部變量1中裝載double類型值
dload_2 從局部變量2中裝載double類型值
dload_3 從局部變量3中裝載double類型值
aload_0 從局部變量0中裝載引用類型值
aload_1 從局部變量1中裝載引用類型值
aload_2 從局部變量2中裝載引用類型值
aload_3 從局部變量3中裝載引用類型值
iaload 從數(shù)組中裝載int類型值
laload 從數(shù)組中裝載long類型值
faload 從數(shù)組中裝載float類型值
daload 從數(shù)組中裝載double類型值
aaload 從數(shù)組中裝載引用類型值
baload 從數(shù)組中裝載byte類型或boolean類型值
caload 從數(shù)組中裝載char類型值
saload 從數(shù)組中裝載short類型值
    1.3  將棧中的值存入局部變量的指令 33

istore 將int類型值存入局部變量
lstore 將long類型值存入局部變量
fstore 將float類型值存入局部變量
dstore 將double類型值存入局部變量
astore 將將引用類型或returnAddress類型值存入局部變量
istore_0 將int類型值存入局部變量0
istore_1 將int類型值存入局部變量1
istore_2 將int類型值存入局部變量2
istore_3 將int類型值存入局部變量3
lstore_0 將long類型值存入局部變量0
lstore_1 將long類型值存入局部變量1
lstore_2 將long類型值存入局部變量2
lstore_3 將long類型值存入局部變量3
fstore_0 將float類型值存入局部變量0
fstore_1 將float類型值存入局部變量1
fstore_2 將float類型值存入局部變量2
fstore_3 將float類型值存入局部變量3
dstore_0 將double類型值存入局部變量0
dstore_1 將double類型值存入局部變量1
dstore_2 將double類型值存入局部變量2
dstore_3 將double類型值存入局部變量3
astore_0 將引用類型或returnAddress類型值存入局部變量0
astore_1 將引用類型或returnAddress類型值存入局部變量1
astore_2 將引用類型或returnAddress類型值存入局部變量2
astore_3 將引用類型或returnAddress類型值存入局部變量3
iastore 將int類型值存入數(shù)組中
lastore 將long類型值存入數(shù)組中
fastore 將float類型值存入數(shù)組中
dastore 將double類型值存入數(shù)組中
aastore 將引用類型值存入數(shù)組中
bastore 將byte類型或者boolean類型值存入數(shù)組中
castore 將char類型值存入數(shù)組中
sastore 將short類型值存入數(shù)組中
2、類型轉(zhuǎn)換 15

i2l 把int類型的數(shù)據(jù)轉(zhuǎn)化為long類型
i2f 把int類型的數(shù)據(jù)轉(zhuǎn)化為float類型
i2d 把int類型的數(shù)據(jù)轉(zhuǎn)化為double類型
l2i 把long類型的數(shù)據(jù)轉(zhuǎn)化為int類型
l2f 把long類型的數(shù)據(jù)轉(zhuǎn)化為float類型
l2d 把long類型的數(shù)據(jù)轉(zhuǎn)化為double類型
f2i 把float類型的數(shù)據(jù)轉(zhuǎn)化為int類型
f2l 把float類型的數(shù)據(jù)轉(zhuǎn)化為long類型
f2d 把float類型的數(shù)據(jù)轉(zhuǎn)化為double類型
d2i 把double類型的數(shù)據(jù)轉(zhuǎn)化為int類型
d2l 把double類型的數(shù)據(jù)轉(zhuǎn)化為long類型
d2f 把double類型的數(shù)據(jù)轉(zhuǎn)化為float類型
i2b 把int類型的數(shù)據(jù)轉(zhuǎn)化為byte類型
i2c 把int類型的數(shù)據(jù)轉(zhuǎn)化為char類型
i2s 把int類型的數(shù)據(jù)轉(zhuǎn)化為short類型
3秉馏、整數(shù)運(yùn)算 13

iadd 執(zhí)行int類型的加法
ladd 執(zhí)行l(wèi)ong類型的加法
isub 執(zhí)行int類型的減法
lsub 執(zhí)行l(wèi)ong類型的減法
imul 執(zhí)行int類型的乘法
lmul 執(zhí)行l(wèi)ong類型的乘法
idiv 執(zhí)行int類型的除法
ldiv 執(zhí)行l(wèi)ong類型的除法
irem 計(jì)算int類型除法的余數(shù)
lrem 計(jì)算long類型除法的余數(shù)
ineg 對(duì)一個(gè)int類型值進(jìn)行取反操作
lneg 對(duì)一個(gè)long類型值進(jìn)行取反操作
iinc 把一個(gè)常量值加到一個(gè)int類型的局部變量上
4瓜挽、邏輯運(yùn)算

4.1  位移操作

1
2
3
4
5
6
ishl 執(zhí)行int類型的向左移位操作
lshl 執(zhí)行l(wèi)ong類型的向左移位操作
ishr 執(zhí)行int類型的向右移位操作
lshr 執(zhí)行l(wèi)ong類型的向右移位操作
iushr 執(zhí)行int類型的向右邏輯移位操作
lushr 執(zhí)行l(wèi)ong類型的向右邏輯移位操作
    4.2  按位布爾運(yùn)算

1
2
3
4
5
6
iand 對(duì)int類型值進(jìn)行“邏輯與”操作
land 對(duì)long類型值進(jìn)行“邏輯與”操作
ior 對(duì)int類型值進(jìn)行“邏輯或”操作
lor 對(duì)long類型值進(jìn)行“邏輯或”操作
ixor 對(duì)int類型值進(jìn)行“邏輯異或”操作
lxor 對(duì)long類型值進(jìn)行“邏輯異或”操作
    4.3  浮點(diǎn)運(yùn)算 12個(gè)

fadd 執(zhí)行float類型的加法
dadd 執(zhí)行double類型的加法
fsub 執(zhí)行float類型的減法
dsub 執(zhí)行double類型的減法
fmul 執(zhí)行float類型的乘法
dmul 執(zhí)行double類型的乘法
fdiv 執(zhí)行float類型的除法
ddiv 執(zhí)行double類型的除法
frem 計(jì)算float類型除法的余數(shù)
drem 計(jì)算double類型除法的余數(shù)
fneg 將一個(gè)float類型的數(shù)值取反
dneg 將一個(gè)double類型的數(shù)值取反
5、對(duì)象和數(shù)組

5.1  對(duì)象操作指令 7

new 創(chuàng)建一個(gè)新對(duì)象
checkcast 確定對(duì)象為所給定的類型
getfield 從對(duì)象中獲取字段
putfield 設(shè)置對(duì)象中字段的值
getstatic 從類中獲取靜態(tài)字段
putstatic 設(shè)置類中靜態(tài)字段的值
instanceof 判斷對(duì)象是否為給定的類型
    5.2  數(shù)組操作指令4

newarray 分配數(shù)據(jù)成員類型為基本上數(shù)據(jù)類型的新數(shù)組
anewarray 分配數(shù)據(jù)成員類型為引用類型的新數(shù)組
arraylength 獲取數(shù)組長度
multianewarray 分配新的多維數(shù)組
6锅铅、控制流

6.1  條件分支指令 16

ifeq 如果等于0,則跳轉(zhuǎn)
ifne 如果不等于0挑胸,則跳轉(zhuǎn)
iflt 如果小于0猴凹,則跳轉(zhuǎn)
ifge 如果大于等于0夷狰,則跳轉(zhuǎn)
ifgt 如果大于0,則跳轉(zhuǎn)
ifle 如果小于等于0郊霎,則跳轉(zhuǎn)
if_icmpcq 如果兩個(gè)int值相等沼头,則跳轉(zhuǎn)
if_icmpne 如果兩個(gè)int類型值不相等,則跳轉(zhuǎn)
if_icmplt 如果一個(gè)int類型值小于另外一個(gè)int類型值书劝,則跳轉(zhuǎn)
if_icmpge 如果一個(gè)int類型值大于或者等于另外一個(gè)int類型值进倍,則跳轉(zhuǎn)
if_icmpgt 如果一個(gè)int類型值大于另外一個(gè)int類型值,則跳轉(zhuǎn)
if_icmple 如果一個(gè)int類型值小于或者等于另外一個(gè)int類型值购对,則跳轉(zhuǎn)
ifnull 如果等于null猾昆,則跳轉(zhuǎn)
ifnonnull 如果不等于null,則跳轉(zhuǎn)
if_acmpeq 如果兩個(gè)對(duì)象引用相等骡苞,則跳轉(zhuǎn)
if_acmpnc 如果兩個(gè)對(duì)象引用不相等垂蜗,則跳轉(zhuǎn)
7、比較指令 5

lcmp 比較long類型值
fcmpl 比較float類型值(當(dāng)遇到NaN時(shí)解幽,返回-1)
fcmpg 比較float類型值(當(dāng)遇到NaN時(shí)贴见,返回1)
dcmpl 比較double類型值(當(dāng)遇到NaN時(shí),返回-1)
dcmpg 比較double類型值(當(dāng)遇到NaN時(shí)躲株,返回1)
8片部、無條件轉(zhuǎn)移指令 2

goto 無條件跳轉(zhuǎn)
goto_w 無條件跳轉(zhuǎn)(寬索引)
9、表跳轉(zhuǎn)指令

1
2
tableswitch 通過索引訪問跳轉(zhuǎn)表霜定,并跳轉(zhuǎn)
lookupswitch 通過鍵值匹配訪問跳轉(zhuǎn)表档悠,并執(zhí)行跳轉(zhuǎn)操作
10、異常5

athrow 拋出異惩疲或錯(cuò)誤
finally子句
jsr 跳轉(zhuǎn)到子例程
jsr_w 跳轉(zhuǎn)到子例程(寬索引)
rct 從子例程返回
11站粟、方法調(diào)用與返回

11.1  方法調(diào)用指令 4

invokcvirtual 運(yùn)行時(shí)按照對(duì)象的類來調(diào)用實(shí)例方法
invokespecial 根據(jù)編譯時(shí)類型來調(diào)用實(shí)例方法
invokestatic 調(diào)用類(靜態(tài))方法
invokcinterface 調(diào)用接口方法
    11.2  方法返回指令 6

ireturn 從方法中返回int類型的數(shù)據(jù)
lreturn 從方法中返回long類型的數(shù)據(jù)
freturn 從方法中返回float類型的數(shù)據(jù)
dreturn 從方法中返回double類型的數(shù)據(jù)
areturn 從方法中返回引用類型的數(shù)據(jù)
return 從方法中返回,返回值為void
12曾雕、線程同步

1
2
montiorenter 進(jìn)入并獲取對(duì)象監(jiān)視器
monitorexit 釋放并退出對(duì)象監(jiān)視器

image.png

jvm 指令 invokevirtual indexbyte1 indexbyte2 方法索引位置 (indexbyte1 << 8) | indexbyte2

1奴烙、Java語言規(guī)范中如何定義boolean?
boolean的取值只有兩種:true或者false
然而這兩個(gè)符號(hào)無法被虛擬機(jī)直接使用
2、JVM規(guī)范是如何定義boolean類型的剖张?
JVM中boolean類型被映射為int類型
true映射為整數(shù)1
false映射為整數(shù)0
————————————————
https://blog.csdn.net/zhoufanyang_china/article/details/86750351 獲取java對(duì)象的內(nèi)存地址

https://blog.csdn.net/u013928208/article/details/106758062 jdk c 源碼 jvm啟動(dòng)分析較好.

先簡(jiǎn)單介紹一下instanceof的字節(jié)碼操作:確定對(duì)象是否為給定的類型指令格式:instanceof|indexbyte1|indexbyte2指令執(zhí)行前后的棧頂狀態(tài):
……切诀,objectref=> 從棧頂彈出
……,result 把結(jié)果壓入棧頂

描述:indexbyte1和indexbyte2用于構(gòu)造對(duì)當(dāng)前類的常量池的索引搔弄,objectref為reference類型幅虑,可以是某個(gè)類,數(shù)組的實(shí)例或者是接口顾犹〉光郑基本的實(shí)現(xiàn)過程:對(duì)indexbyte1和indexbyte2構(gòu)造的常量池索引進(jìn)行解析褒墨,然后根據(jù)java規(guī)范判斷解析的類是不是objectref的一個(gè)實(shí)例,最后在棧頂寫入結(jié)果擎宝。大體是這么個(gè)過程郁妈,沒有詳細(xì)列舉細(xì)節(jié)

jvm 常量池排列算法. : 添加class 首先看有沒有對(duì)應(yīng)的utf8 沒有 則建立后再加入class
這樣引用就不會(huì)出錯(cuò). 但asm 項(xiàng)目 49 [1.5] 顯示出來的是 正序. jdk 1.8 顯示反序

  int addConstantNameAndType(final String name, final String descriptor) {
    final int tag = Symbol.CONSTANT_NAME_AND_TYPE_TAG;
    int hashCode = hash(tag, name, descriptor);
    Entry entry = get(hashCode);
    while (entry != null) {
      if (entry.tag == tag
          && entry.hashCode == hashCode
          && entry.name.equals(name)
          && entry.value.equals(descriptor)) {
        return entry.index;
      }
      entry = entry.next;
    }
//此處嵌套添加. 要想 添加 addConstantNameAndType 則必須先添加 utf8... good!! 晚安 小姑姑. 南無阿彌陀佛 南無地藏王菩薩 
    constantPool.put122(tag, addConstantUtf8(name), addConstantUtf8(descriptor));
    return put(new Entry(constantPoolCount++, tag, name, descriptor, hashCode)).index;
  }

jvm包括兩種數(shù)據(jù)類型,基本類型和引用類型绍申。

基本類型包括噩咪,數(shù)值類型,boolean類型极阅,和returnAddress類型胃碾。

數(shù)值類型包括,整型筋搏,浮點(diǎn)型仆百,和char類型。

boolean類型同樣只有true和false奔脐。

returnAddress類型是一個(gè)指針俄周,指向jvm指令的操作碼,在Java中沒有與之對(duì)應(yīng)的類型帖族。

boolean類型的操作會(huì)被轉(zhuǎn)化為int類型的操作進(jìn)行栈源,boolean數(shù)組會(huì)當(dāng)成byte數(shù)組去操作挡爵。1表示true竖般,0表示false。

引用類型包括三種茶鹃,類類型涣雕,數(shù)組類型,和接口類型闭翩。

有三種reference 類型:類類型挣郭,數(shù)組類型和接口類型。它們的值分別引用動(dòng)態(tài)創(chuàng)建的類實(shí)例疗韵,數(shù)組或?qū)崿F(xiàn)接口的類實(shí)例或數(shù)組兑障。

數(shù)組類型由具有單個(gè)維度的組件類型組成 (其長度未由類型指定)。數(shù)組類型的組件類型本身可以是數(shù)組類型蕉汪。如果從任何數(shù)組類型開始流译,先考慮其組件類型,然后再考慮(如果也是數(shù)組類型)該類型的組件類型者疤,依此類推福澡,則最終必須達(dá)到不是數(shù)組類型的組件類型;這稱為數(shù)組類型的元素類型驹马。數(shù)組類型的元素類型必須是原始類型革砸,類類型或接口類型除秀。

reference值也可以是專用空引用的,沒有對(duì)象的引用算利,這將在這里通過來表示null册踩。該null引用最初沒有運(yùn)行時(shí)類型,但可以強(qiáng)制轉(zhuǎn)換為任何類型笔时。reference類型的默認(rèn)值是null棍好。

本規(guī)范不要求進(jìn)行具體的值編碼null

jvm 指令與相對(duì)類型 匹配
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.11.1

數(shù)據(jù)類型
在 JVM 中允耿,數(shù)據(jù)分為兩大類:primitive types (原生類型)和 reference types(引用類型)借笙。

引用類型,讓 JVM 能更好的支持于面向?qū)ο笳Z言的設(shè)計(jì)较锡,引用類型的值用來指向內(nèi)存中分配的類實(shí)例或者數(shù)組业稼。JVM 規(guī)范中并沒有詳細(xì)規(guī)定引用類型的實(shí)現(xiàn)細(xì)節(jié),比如引用應(yīng)該通過何種方式去定位蚂蕴、訪問堆中的對(duì)象低散,具體的對(duì)象訪問方式取決于虛擬機(jī)的具體實(shí)現(xiàn),比如 HotSpot 有其自己的實(shí)現(xiàn)方案骡楼。

目前主流的訪問方式有使用句柄和直接指針兩種:

其中使用直接指針訪問的方式熔号,類似于 C++ 中的虛表(虛表就是指向?qū)ο箢愋蛿?shù)據(jù)的指針)。這兩種對(duì)象訪問方式各有優(yōu)劣鸟整,使用句柄訪問的最大好處就是 reference 中存儲(chǔ)的是穩(wěn)定的句柄地址引镊,在對(duì)象被移動(dòng)(比如垃圾回收時(shí),整理內(nèi)存空間篮条,會(huì)移動(dòng)對(duì)象的存儲(chǔ)位置)時(shí)只會(huì)改變句柄中示例數(shù)據(jù)的指針弟头,而 reference 本身不需要修改。

使用直接指針訪問的最大好處就是速度更快涉茧,節(jié)省了一次內(nèi)存尋址的時(shí)間開銷赴恨。

原生數(shù)據(jù)類型包括:numeric types, boolean type, returnAddress type。其中 returnAddress 數(shù)據(jù)只存在于字節(jié)碼層面伴栓,與編程語言無關(guān)伦连,也就是說,我們?cè)?Java 語言中是不會(huì)直接與 returnAddress 類型的數(shù)據(jù)打交道的钳垮。

returnAddress 類型的值是指向字節(jié)碼的指針惑淳,不管是物理機(jī)還是虛擬機(jī),運(yùn)行時(shí)內(nèi)存中的數(shù)據(jù)總歸可分為兩類:代碼扔枫,數(shù)據(jù)汛聚。對(duì)于馮諾依曼結(jié)構(gòu)的計(jì)算機(jī),指令數(shù)據(jù)和數(shù)值數(shù)據(jù)都存儲(chǔ)在內(nèi)存中短荐,而哈弗結(jié)構(gòu)的計(jì)算機(jī)倚舀,將程序指令與數(shù)據(jù)分開存儲(chǔ)叹哭。

對(duì)于 JVM 來說,程序就是存儲(chǔ)在方法區(qū)的字節(jié)碼指令痕貌,而 returnAddress 類型的值就是指向特定指令內(nèi)存地址的指針风罩。

JVM支持多線程,每個(gè)線程有自己的程序計(jì)數(shù)器(pc register)舵稠,而 pc 中的值就是當(dāng)前指令所在的內(nèi)存地址超升,即 returnAddress 類型的數(shù)據(jù),當(dāng)線程執(zhí)行 native 方法時(shí)哺徊,pc 中的值為 undefined室琢。

棧幀
棧幀(Stack Frame)是用于支持虛擬機(jī)進(jìn)行方法調(diào)用和方法執(zhí)行的數(shù)據(jù)結(jié)構(gòu),棧幀中存儲(chǔ)了方法的局部變量表落追,操作數(shù)棧盈滴,動(dòng)態(tài)連接,和方法返回地址等信息轿钠。在程序編譯時(shí)巢钓,棧幀中需要多大的局部變量表,多深的操作數(shù)棧都已經(jīng)完全確定了疗垛,并且寫在方法表的 Code 屬性中症汹。

當(dāng)一個(gè)方法開始執(zhí)行后,只有兩種方式可以退出贷腕,第一種方式是執(zhí)行引擎遇到任意一個(gè)方法返回的字節(jié)碼指令背镇,這種方式稱為正常完成出口;另外一種退出方式是花履,在方法執(zhí)行過程中遇到異常芽世,且該異常沒有被被捕獲挚赊,稱為異常完成出口诡壁。

無論是哪種退出方式,在方法退出后荠割,都需要返回到該方法被調(diào)用的位置(地址)妹卿,讓程序繼續(xù)執(zhí)行。一般來說蔑鹦,方法執(zhí)行前夺克,會(huì)保存調(diào)用者當(dāng)前的 PC 計(jì)數(shù)器中的值,當(dāng)方法正常退出時(shí)嚎朽,將該 PC 計(jì)數(shù)器的值會(huì)作為返回地址铺纽,返回給調(diào)用者。在方法異常退出時(shí)哟忍,返回地址是通過異常處理器表來確定的狡门。

方法退出的過程實(shí)際上就等于把當(dāng)前棧幀出棧陷寝,一般過程為:

恢復(fù)上層方法的局部變量表和操作數(shù)棧
把返回值壓入調(diào)用者棧幀的操作數(shù)棧中
調(diào)整 PC 計(jì)數(shù)器的值,以指向方法調(diào)用指令后面的一條指令

《Thinking in Java》中寫到:如果對(duì)char其馏、byte 或者 short類型的數(shù)值進(jìn)行移位處理凤跑,那么在移位進(jìn)行之前,它們會(huì)被轉(zhuǎn)換為int類型叛复,并且得到的結(jié)果也是一個(gè)int類型仔引。只有數(shù)值右端的低5位才有用。這樣可以防止我們移位超過int型值所具有的位數(shù)褐奥。
byte咖耘、short、int撬码、char類型的數(shù)據(jù)經(jīng)過移位運(yùn)算后結(jié)果都為int型鲤看。
long經(jīng)過移位運(yùn)算后結(jié)果為long型。
https://blog.csdn.net/chattie/article/details/4029922

例如第一個(gè)byte 為1 則 左移 8位則為 256

https://www.cnblogs.com/Yee-Q/p/14250375.html

可以發(fā)現(xiàn)耍群,大部分指令都沒有支持 byte义桂、char、short蹈垢、boolean慷吊,編譯器會(huì)在編譯期或運(yùn)行期將 byte 和 short 類型的數(shù)據(jù)帶符號(hào)擴(kuò)展為相應(yīng)的 int 類型數(shù)據(jù),將 boolean 和 char 類型數(shù)據(jù)零位擴(kuò)展為相應(yīng)的 int 類型數(shù)據(jù)曹抬,然后使用對(duì)應(yīng) int 類型的字節(jié)碼指令來處理溉瓶。因此,大多數(shù)對(duì)于 boolean谤民、byte堰酿、short 和 char 類型數(shù)據(jù)的操作,實(shí)際上都是轉(zhuǎn)換成 int 類型再進(jìn)行操作

https://docs.oracle.com/javase/specs/jvms/se9/html/jvms-4.html#jvms-4.4
官方文檔(最好的jvm教程)

由于限制了Java虛擬機(jī)操作碼的長度為一個(gè)字節(jié)(即0~255)张足,這意味著指令集的操作碼總數(shù)不可能超過256條触创。

jvm的opcode都是占一個(gè)字節(jié),所以jvm虛擬機(jī)最多可有256條opcode为牍。目前jvm規(guī)范8中列出的opcode有0x000xc9(0201)哼绑,加上3個(gè)保留opcode 0xca,0xfe,0xff(202,254,255),共205條碉咆。
三個(gè)保留操作碼:

254(0xfe) impdep1 后門
255(0xff) impdep2 陷進(jìn)
202(0xca) breakpoint 斷點(diǎn)

其中前203條的編碼都是連續(xù)的抖韩,很有規(guī)律。

其中疫铜,操作碼值分別為 254(0xfe)和 255(0xff)茂浮,助記符分別為 impdep1 和 impdep2的兩個(gè)操作碼是作為“后門”和“陷阱”出現(xiàn),目的是在某些硬件和軟件中提供一些與實(shí)現(xiàn)相關(guān)的功能。第三個(gè)操作碼值分別為 202(0xca)席揽、助記符為 breakpoint 的操作碼是用于調(diào)試器實(shí)現(xiàn)斷點(diǎn)功能佃乘。

你開發(fā)的系統(tǒng)是 裸奔 的嗎?深夜被老板 Diss
一套系統(tǒng)是否穩(wěn)定運(yùn)行驹尼,取決于它的運(yùn)行健康度趣避,而這包括; 調(diào)用量 新翎、 可用率 程帕、 響應(yīng)時(shí)長 以及服務(wù)器
性能等各項(xiàng)指標(biāo)的一個(gè)綜合值。并且在系統(tǒng)出現(xiàn)異常問題時(shí)地啰,可以抓取整個(gè)業(yè)務(wù)方法執(zhí)行鏈路并輸出愁拭;
當(dāng)時(shí)的入?yún)ⅰ⒊鰠⒖髁摺惓P畔⒌鹊攘氩骸.?dāng)然還包括一些JVM、Redis蔚鸥、Mysql的各項(xiàng)性能指標(biāo)惜论,以用于快速
定位并解決問題。

那么要做到這樣的事情有什么監(jiān)控方案呢止喷,這里面的做法比較多馆类。比如;

  1. 最簡(jiǎn)單粗暴的可能就是硬編碼在方法中弹谁,收取執(zhí)行耗時(shí)以及出入?yún)⒑彤惓P畔⑶伞5@樣的成本實(shí)在
    太大,而且有一些不可預(yù)估的風(fēng)險(xiǎn)预愤。
  2. 可以選擇切面方式做一套統(tǒng)一監(jiān)控的組件沟于,相對(duì)來說還是好一些的。但也需要硬編碼植康,同時(shí)維護(hù)成
    本不低旷太。
  3. 市面上對(duì)于這樣的監(jiān)控其實(shí)是有整套的非入侵監(jiān)控方案的,比如向图; Google Dapper 泳秀、 Zipkin 等
    都可以實(shí)現(xiàn)标沪,他們都是基于探針技術(shù)非入侵的采用字節(jié)碼增強(qiáng)的方式進(jìn)行監(jiān)控榄攀。
    好,那么這樣非入侵的探針方式是怎么實(shí)現(xiàn)的呢金句?如何去做方法的 字節(jié)碼增強(qiáng) 檩赢?
    在字節(jié)碼增強(qiáng)方面有三個(gè)框架; ASM 、 Javassist 贞瞒、 ByteCode 偶房,各有優(yōu)缺點(diǎn)按需選擇。這在我們之前
    的字節(jié)碼編程文章里也有所提到军浆。

reference
reference是一個(gè)對(duì)象實(shí)例的引用

作用:
從此引用中直接或間接地查找到對(duì)象在Java堆中的數(shù)據(jù)存放的起始地址索引
從此引用中直接或間接地查找到對(duì)象所屬數(shù)據(jù)類型在方法區(qū)中的存儲(chǔ)的類型對(duì)象(因?yàn)轭愋畔⒃诜椒▍^(qū)中存儲(chǔ))

java 編譯的官方 good
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-3.html

package com.rumenz;

public class rumenz{
      public Integer id=10;
      public String  name="入門";
      public final int  age=100;
      public void setId(Integer id){
          this.id=id;
      }
}
javap 后的
> javac rumenz.java
> javap -v rumenz

Classfile /code/rumenz.class
  Last modified 2020-10-17; size 542 bytes
  MD5 checksum 6a8a73fb6327c1a64e9ad54e53e94afd
  Compiled from "rumenz.java"
public class com.rumenz.rumenz
  minor version: 0
  major version: 52
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #9.#24         // java/lang/Object."<init>":()V
   #2 = Fieldref           #8.#25         // com/rumenz/rumenz.id:I
   #3 = String             #26            // 入門
   #4 = Fieldref           #8.#27         // com/rumenz/rumenz.name:Ljava/lang/String;
   #5 = Methodref          #28.#29        // java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
   #6 = Fieldref           #8.#30         // com/rumenz/rumenz.age:Ljava/lang/Integer;
   #7 = Methodref          #28.#31        // java/lang/Integer.intValue:()I
   #8 = Class              #32            // com/rumenz/rumenz
   #9 = Class              #33            // java/lang/Object
  #10 = Utf8               id
  #11 = Utf8               I
  #12 = Utf8               name
  #13 = Utf8               Ljava/lang/String;
  #14 = Utf8               age
  #15 = Utf8               Ljava/lang/Integer;
  #16 = Utf8               <init>
  #17 = Utf8               ()V
  #18 = Utf8               Code
  #19 = Utf8               LineNumberTable
  #20 = Utf8               setId
  #21 = Utf8               (Ljava/lang/Integer;)V
  #22 = Utf8               SourceFile
  #23 = Utf8               rumenz.java
  #24 = NameAndType        #16:#17        // "<init>":()V
  #25 = NameAndType        #10:#11        // id:I
  #26 = Utf8               入門
  #27 = NameAndType        #12:#13        // name:Ljava/lang/String;
  #28 = Class              #34            // java/lang/Integer
  #29 = NameAndType        #35:#36        // valueOf:(I)Ljava/lang/Integer;
  #30 = NameAndType        #14:#15        // age:Ljava/lang/Integer;
  #31 = NameAndType        #37:#38        // intValue:()I
  #32 = Utf8               com/rumenz/rumenz
  #33 = Utf8               java/lang/Object
  #34 = Utf8               java/lang/Integer
  #35 = Utf8               valueOf
  #36 = Utf8               (I)Ljava/lang/Integer;
  #37 = Utf8               intValue
  #38 = Utf8               ()I
{
  public int id;
    descriptor: I
    flags: ACC_PUBLIC

  public java.lang.String name;
    descriptor: Ljava/lang/String;
    flags: ACC_PUBLIC

  public final java.lang.Integer age;
    descriptor: Ljava/lang/Integer;
    flags: ACC_PUBLIC, ACC_FINAL

  public com.rumenz.rumenz();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: aload_0
         5: bipush        10
         7: putfield      #2                  // Field id:I
        10: aload_0
        11: ldc           #3                  // String 入門
        13: putfield      #4                  // Field name:Ljava/lang/String;
        16: aload_0
        17: bipush        100
        19: invokestatic  #5                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
        22: putfield      #6                  // Field age:Ljava/lang/Integer;
        25: return
      LineNumberTable:
        line 11: 0
        line 12: 4
        line 13: 10
        line 14: 16

  public void setId(java.lang.Integer);
    descriptor: (Ljava/lang/Integer;)V
    flags: ACC_PUBLIC
    Code:
      stack=3, locals=3, args_size=2
         0: aload_0
         1: iconst_3
         2: aload_1
         3: invokevirtual #7                  // Method java/lang/Integer.intValue:()I
         6: iadd
         7: putfield      #2                  // Field id:I
        10: return
      LineNumberTable:
        line 17: 0
        line 18: 10
}
SourceFile: "rumenz.java"

jvm 常量池?cái)?shù)據(jù)結(jié)構(gòu)
https://blog.csdn.net/weixin_33796177/article/details/91700668

hotspot 分析
https://www.cnblogs.com/dennyzhangdd/p/6734933.html

JVM中 int 類型數(shù)值棕洋,根據(jù) 取值范圍將 入棧的 字節(jié)碼指令 就分為4類:

取值 -1~5 采用 iconst 指令;

取值 -128~127 采用 bipush 指令乒融;

取值 -32768~32767 采用 sipush指令掰盘;

取值 -2147483648~2147483647 采用 ldc 指令。

注意赞季,上圖中l(wèi)dc指令是從常量池中取值的愧捕,ldc指令用于將int、float申钩、String類型常量從常量池中壓到棧頂次绘,在這段范圍(-2147483648~2147483647)內(nèi)的int值存儲(chǔ)在常量池中。
jvm指令大部分1個(gè)字節(jié)
少部分 帶2個(gè)操作數(shù)
MULTIANEWARRAY 3個(gè)操作數(shù)
.只有JSR_W GOTO_W invokeinterface invokedynamic 是4字節(jié))

iconst撒遣、bipush怯屉、sipush墓捻、ldc指令的區(qū)別

java 虛擬機(jī)的命令由一個(gè)操作碼(Opcode)以及零或多個(gè)操作數(shù)(Operands)組成。其中,操作碼是一個(gè)字節(jié)長度的數(shù)字蔑水,不同的數(shù)字代表不同的操作碼。對(duì)于操作數(shù)而言垦搬,一個(gè)字節(jié)碼的數(shù)字代表一個(gè)操作數(shù)皮钠。由于 java 虛擬機(jī)采用面向操作數(shù)棧而不是寄存器的架構(gòu),因此火的,大多數(shù)的命令都不包含操作數(shù)壶愤,只有一個(gè)操作碼。

在 java 虛擬機(jī)的命令集中馏鹤,大多數(shù)的命令都包含了其操作所對(duì)應(yīng)的數(shù)據(jù)類型信息征椒,在這些命令中,操作碼中第一個(gè)字母表明了其數(shù)據(jù)類型:i 代表 int湃累,l 代表 long勃救,s 代表 short,b 代表 byte治力,c 代表 char蒙秒,f 代表 float,d 代表 double宵统,a 代表 reference晕讲。

由于操作碼只占一個(gè)字節(jié),所以最多只有 256 個(gè)命令,這也決定了 java 虛擬機(jī)中只對(duì)一些常用的操作提供了有限的類型相關(guān)識(shí)別命令瓢省,對(duì)于剩下的部分弄息,java 虛擬機(jī)通過類型轉(zhuǎn)換將其他類型轉(zhuǎn)成虛擬機(jī)命令支持的類型然而再進(jìn)行操作。

由于虛擬機(jī)命令很多勤婚,而且部分命令功能類似摹量,所以本文只介紹部分常用的命令。

加載命令

加載命令是指將數(shù)據(jù)在棧幀中的局部變量表加載到操作數(shù)棧中馒胆。其主要的命令包括兩種:將一個(gè)局部變量加載到操作數(shù)棧和將一個(gè)常量加載到操作數(shù)棧荆永。

加載局部變量

部分常見的加載局部變量的命令如下所示

助記符 操作數(shù) 含義
iload 一個(gè),i 加載第 i 個(gè) int 類型的局部變量国章,i 從 0 開始計(jì)數(shù)
iload_0 0 加載第 0 個(gè) int 類型的局部變量具钥,與 iload 0 命令相同
iload_1 加載第 1 個(gè) int 類型的局部變量,與 iload 1 命令相同
iload_2 加載第 2 個(gè) int 類型的局部變量液兽,與 iload 2 命令相同
iload_3 加載第 3 個(gè) int 類型的局部變量骂删,與 iload 3 命令相同
lload 一個(gè),i 加載第 i 個(gè) long 類型的局部變量四啰,i 從 0 開始計(jì)數(shù)
lload_0 加載第 0 個(gè) long 類型的局部變量宁玫,與 lload 0 命令相同
lload_1 加載第 1 個(gè) long 類型的局部變量,與 lload 1 命令相同
lload_2 加載第 2 個(gè) long 類型的局部變量柑晒,與 lload 2 命令相同
lload_3 加載第 3 個(gè) long 類型的局部變量欧瘪,與 lload 3 命令相同
fload 一個(gè),i 加載第 i 個(gè) float 類型的局部變量匙赞,i 從 0 開始計(jì)數(shù)
fload_0 加載第 0 個(gè) float 類型的局部變量佛掖,與 fload 0 命令相同
fload_1 加載第 1 個(gè) float 類型的局部變量,與 fload 1 命令相同
fload_2 加載第 2 個(gè) float 類型的局部變量涌庭,與 fload 2 命令相同
fload_3 加載第 3 個(gè) float 類型的局部變量芥被,與 fload 3 命令相同
dload 一個(gè),i 加載第 i 個(gè) double 類型的局部變量坐榆,i 從 0 開始計(jì)數(shù)
dload_0 加載第 0 個(gè) double 類型的局部變量拴魄,與 dload 0 命令相同
dload_1 加載第 1 個(gè) double 類型的局部變量,與 dload 1 命令相同
dload_2 加載第 2 個(gè) double 類型的局部變量席镀,與 dload 2 命令相同
dload_3 加載第 3 個(gè) double 類型的局部變量匹中,與 dload 3 命令相同
aload 一個(gè),i 加載第 i 個(gè) 引用類型的局部變量豪诲,i 從 0 開始計(jì)數(shù)
aload_0 加載第 0 個(gè) 引用類型的局部變量顶捷,與 aload 0 命令相同
aload_1 加載第 1 個(gè) 引用類型的局部變量,與 aload 1 命令相同
aload_2 加載第 2 個(gè) 引用類型的局部變量跛溉,與 aload 2 命令相同
aload_3 加載第 3 個(gè) 引用類型的局部變量焊切,與 aload 3 命令相同

加載常量

部分常見的加載常量的命令如下所示

操作碼 操作數(shù) 含義
bipush 一個(gè)扮授,i 將單字節(jié)的常量值 i (-128 ~ 127)推送到棧頂
sipush 兩個(gè)芳室,byte1, byte2 將 byte1 和 byte2 進(jìn)行 ((byte1 << 8) byte2) 運(yùn)算专肪,得到 short 類型(-32768 ~ 32767),并將其推送到棧頂
ldc 一個(gè)堪侯,i 與 ldc_w 類似嚎尤,將常量池中第 i 個(gè)(從 1 開始計(jì)數(shù))常量的值取出推送到棧頂,類型可以是 int伍宦、float芽死、String。當(dāng)常量池中常量數(shù)量不超過 255 個(gè)時(shí)次洼,使用此命令关贵,否則使用 ldc_w
ldc_w 兩個(gè),indexbyte1卖毁,indexbyte2 與 ldc 類似揖曾,將常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量的值取出推送到棧頂,類型可以是 int亥啦、float炭剪、String。當(dāng)常量池中常量數(shù)量超過 255 個(gè)時(shí)翔脱,使用此命令奴拦,否則使用 ldc
ldc2_w 兩個(gè),indexbyte1届吁,indexbyte2 將常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量的值取出推送到棧頂错妖,類型可以是 long 或 double
aconst_null 將一個(gè) null 推送到棧頂
iconst_m1 將數(shù)字 -1(int 類型)推送到棧頂
iconst_0 將數(shù)字 0(int 類型)推送到棧頂
iconst_1 將數(shù)字 1(int 類型)推送到棧頂
iconst_2 將數(shù)字 2(int 類型)推送到棧頂
iconst_3 將數(shù)字 3(int 類型)推送到棧頂
iconst_4 將數(shù)字 4(int 類型)推送到棧頂
iconst_5 將數(shù)字 5(int 類型)推送到棧頂
lconst_0 將數(shù)字 0(long 類型)推送到棧頂
lconst_1 將數(shù)字 1(long 類型)推送到棧頂
fconst_0 將數(shù)字 0(float 類型)推送到棧頂
fconst_1 將數(shù)字 1(float 類型)推送到棧頂
fconst_2 將數(shù)字 2(float 類型)推送到棧頂
dconst_0 將數(shù)字 0(double 類型)推送到棧頂
dconst_1 將數(shù)字 1(double 類型)推送到棧頂

存儲(chǔ)命令

存儲(chǔ)命令主要是將一個(gè)數(shù)值從操作數(shù)棧存儲(chǔ)到局部變量表中,常見的命令如下

助記符 操作數(shù) 含義
istore 一個(gè)疚沐,i 將棧頂 int 類型數(shù)值存入第 i 個(gè)(從 0 開始計(jì)數(shù))本地局部變量
istore_0 將棧頂 int 類型的數(shù)值存入第 0 個(gè)本地局部變量站玄,與 istore 0 命令相同
istore_1 將棧頂 int 類型的數(shù)值存入第 1 個(gè)本地局部變量,與 istore 1 命令相同
istore_2 將棧頂 int 類型的數(shù)值存入第 2 個(gè)本地局部變量濒旦,與 istore 2 命令相同
istore_3 將棧頂 int 類型的數(shù)值存入第 3 個(gè)本地局部變量株旷,與 istore 3 命令相同
lstore 一個(gè),i 將棧頂 long 類型數(shù)值存入第 i 個(gè)(從 0 開始計(jì)數(shù))本地局部變量
lstore_0 將棧頂 long 類型的數(shù)值存入第 0 個(gè)本地局部變量尔邓,與 lstore 0 命令相同
lstore_1 將棧頂 long 類型的數(shù)值存入第 1 個(gè)本地局部變量晾剖,與 lstore 1 命令相同
lstore_2 將棧頂 long 類型的數(shù)值存入第 2 個(gè)本地局部變量,與 lstore 2 命令相同
lstore_3 將棧頂 long 類型的數(shù)值存入第 3 個(gè)本地局部變量梯嗽,與 lstore 3 命令相同
fstore 一個(gè)齿尽,i 將棧頂 float 類型數(shù)值存入第 i 個(gè)(從 0 開始計(jì)數(shù))本地局部變量
fstore_0 將棧頂 float 類型的數(shù)值存入第 0 個(gè)本地局部變量,與 fstore 0 命令相同
fstore_1 將棧頂 float 類型的數(shù)值存入第 1 個(gè)本地局部變量灯节,與 fstore 1 命令相同
fstore_2 將棧頂 float 類型的數(shù)值存入第 2 個(gè)本地局部變量循头,與 fstore 2 命令相同
fstore_3 將棧頂 float 類型的數(shù)值存入第 3 個(gè)本地局部變量绵估,與 fstore 3 命令相同
dstore 一個(gè),i 將棧頂 double 類型數(shù)值存入第 i 個(gè)(從 0 開始計(jì)數(shù))本地局部變量
dstore_0 將棧頂 double 類型的數(shù)值存入第 0 個(gè)本地局部變量卡骂,與 dstore 0 命令相同
dstore_1 將棧頂 double 類型的數(shù)值存入第 1 個(gè)本地局部變量国裳,與 dstore 1 命令相同
dstore_2 將棧頂 double 類型的數(shù)值存入第 2 個(gè)本地局部變量,與 dstore 2 命令相同
dstore_3 將棧頂 double 類型的數(shù)值存入第 3 個(gè)本地局部變量全跨,與 dstore 3 命令相同
astore 一個(gè)缝左,i 將棧頂引用類型數(shù)值存入第 i 個(gè)(從 0 開始計(jì)數(shù))本地局部變量
astore_0 將棧頂引用類型的數(shù)值存入第 0 個(gè)本地局部變量,與 astore 0 命令相同
astore_1 將棧頂引用類型的數(shù)值存入第 1 個(gè)本地局部變量浓若,與 astore 1 命令相同
astore_2 將棧頂引用類型的數(shù)值存入第 2 個(gè)本地局部變量渺杉,與 astore 2 命令相同
astore_3 將棧頂引用類型的數(shù)值存入第 3 個(gè)本地局部變量,與 astore 3 命令相同

運(yùn)算命令

運(yùn)算命令用于對(duì)兩個(gè)操作數(shù)棧上的數(shù)值進(jìn)行某種特定的運(yùn)算挪钓,并將結(jié)果重新存入到操作數(shù)棧中是越。運(yùn)算命令包括:加法命令、減法命令碌上、乘法命令倚评、除法命令、求余命令绍赛、取反命令蔓纠、位移命令、按位或命令吗蚌、按位與命令腿倚、按位異或命令、局部變量自增命令蚯妇、比較命令敷燎。

加法命令

助記符 操作數(shù) 含義
iadd 將棧頂兩個(gè) int 類型的數(shù)值出棧,對(duì)其求和箩言,并將結(jié)果壓入棧中
ladd 將棧頂兩個(gè) long 類型的數(shù)值出棧硬贯,對(duì)其求和,并將結(jié)果壓入棧中
fadd 將棧頂兩個(gè) float 類型的數(shù)值出棧陨收,對(duì)其求和饭豹,并將結(jié)果壓入棧中
dadd 將棧頂兩個(gè) double 類型的數(shù)值出棧,對(duì)其求和务漩,并將結(jié)果壓入棧中

減法命令

助記符 操作數(shù) 含義
isub 將棧頂兩個(gè) int 類型的數(shù)值出棧拄衰,以第一個(gè)棧頂元素為減數(shù),第二個(gè)棧頂元素為被減數(shù)饵骨,對(duì)其求差翘悉,并將結(jié)果壓入棧中
lsub 將棧頂兩個(gè) long 類型的數(shù)值出棧,以第一個(gè)棧頂元素為減數(shù)居触,第二個(gè)棧頂元素為被減數(shù)妖混,對(duì)其求差老赤,并將結(jié)果壓入棧中
fsub 將棧頂兩個(gè) float 類型的數(shù)值出棧,以第一個(gè)棧頂元素為減數(shù)制市,第二個(gè)棧頂元素為被減數(shù)抬旺,對(duì)其求差,并將結(jié)果壓入棧中
dsub 將棧頂兩個(gè) double 類型的數(shù)值出棧息堂,以第一個(gè)棧頂元素為減數(shù)嚷狞,第二個(gè)棧頂元素為被減數(shù)块促,對(duì)其求差荣堰,并將結(jié)果壓入棧中

乘法命令

助記符 操作數(shù) 含義
imul 將棧頂兩個(gè) int 類型的數(shù)值出棧,對(duì)其求積竭翠,并將結(jié)果壓入棧中
lmul 將棧頂兩個(gè) long 類型的數(shù)值出棧振坚,對(duì)其求積,并將結(jié)果壓入棧中
fmul 將棧頂兩個(gè) float 類型的數(shù)值出棧斋扰,對(duì)其求積渡八,并將結(jié)果壓入棧中
dmul 將棧頂兩個(gè) double 類型的數(shù)值出棧,對(duì)其求積传货,并將結(jié)果壓入棧中

除法命令

助記符 操作數(shù) 含義
idiv 將棧頂兩個(gè) int 類型的數(shù)值出棧屎鳍,以第一個(gè)棧頂元素為除數(shù),第二個(gè)棧頂元素為被除數(shù)问裕,對(duì)其求商逮壁,并將結(jié)果壓入棧中
ldiv 將棧頂兩個(gè) long 類型的數(shù)值出棧,以第一個(gè)棧頂元素為除數(shù)粮宛,第二個(gè)棧頂元素為被除數(shù)窥淆,對(duì)其求商,并將結(jié)果壓入棧中
fdiv 將棧頂兩個(gè) float 類型的數(shù)值出棧巍杈,以第一個(gè)棧頂元素為除數(shù)忧饭,第二個(gè)棧頂元素為被除數(shù),對(duì)其求商筷畦,并將結(jié)果壓入棧中
ddiv 將棧頂兩個(gè) double 類型的數(shù)值出棧词裤,以第一個(gè)棧頂元素為除數(shù),第二個(gè)棧頂元素為被除數(shù)鳖宾,對(duì)其求商吼砂,并將結(jié)果壓入棧中

求余命令

助記符 操作數(shù) 含義
irem 將棧頂兩個(gè) int 類型的數(shù)值出棧,以第一個(gè)棧頂元素為除數(shù)攘滩,第二個(gè)棧頂元素為被除數(shù)帅刊,對(duì)其求余,并將結(jié)果壓入棧中
lrem 將棧頂兩個(gè) long 類型的數(shù)值出棧漂问,以第一個(gè)棧頂元素為除數(shù)赖瞒,第二個(gè)棧頂元素為被除數(shù)女揭,對(duì)其求余,并將結(jié)果壓入棧中
frem 將棧頂兩個(gè) float 類型的數(shù)值出棧栏饮,以第一個(gè)棧頂元素為除數(shù)吧兔,第二個(gè)棧頂元素為被除數(shù),對(duì)其求余袍嬉,并將結(jié)果壓入棧中
drem 將棧頂兩個(gè) double 類型的數(shù)值出棧境蔼,以第一個(gè)棧頂元素為除數(shù),第二個(gè)棧頂元素為被除數(shù)伺通,對(duì)其求余箍土,并將結(jié)果壓入棧中

取反命令

助記符 操作數(shù) 含義
ineg 將棧頂 int 類型的數(shù)值出棧,取反罐监,并將結(jié)果壓入棧中
lneg 將棧頂 long 類型的數(shù)值出棧吴藻,取反,并將結(jié)果壓入棧中
fneg 將棧頂 float 類型的數(shù)值出棧弓柱,取反沟堡,并將結(jié)果壓入棧中
dneg 將棧頂 double 類型的數(shù)值出棧,取反矢空,并將結(jié)果壓入棧中

位移命令

助記符 操作數(shù) 含義
ishl 將棧頂兩個(gè) int 類型的數(shù)值出棧航罗,以第一個(gè)棧頂元素為移動(dòng)位數(shù),第二個(gè)棧頂元素為位移數(shù)屁药,進(jìn)行左位移操作粥血,并將結(jié)果壓入棧中
lshl 將棧頂兩個(gè) long 類型的數(shù)值出棧,以第一個(gè)棧頂元素為移動(dòng)位數(shù)者祖,第二個(gè)棧頂元素為位移數(shù)立莉,進(jìn)行左位移操作,并將結(jié)果壓入棧中
ishr 將棧頂兩個(gè) int 類型的數(shù)值出棧七问,以第一個(gè)棧頂元素為移動(dòng)位數(shù)蜓耻,第二個(gè)棧頂元素為位移數(shù),進(jìn)行帶符號(hào)右位移操作械巡,并將結(jié)果壓入棧中
lshr 將棧頂兩個(gè) long 類型的數(shù)值出棧刹淌,以第一個(gè)棧頂元素為移動(dòng)位數(shù),第二個(gè)棧頂元素為位移數(shù)讥耗,進(jìn)行帶符號(hào)右位移操作有勾,并將結(jié)果壓入棧中
iushr 將棧頂兩個(gè) int 類型的數(shù)值出棧,以第一個(gè)棧頂元素為移動(dòng)位數(shù)古程,第二個(gè)棧頂元素為位移數(shù)蔼卡,進(jìn)行無符號(hào)右位移操作,并將結(jié)果壓入棧中
lushr 將棧頂兩個(gè) long 類型的數(shù)值出棧挣磨,以第一個(gè)棧頂元素為移動(dòng)位數(shù)雇逞,第二個(gè)棧頂元素為位移數(shù)荤懂,進(jìn)行無符號(hào)右位移操作,并將結(jié)果壓入棧中

按位或命令

助記符 操作數(shù) 含義
ior 將棧頂兩個(gè) int 類型的數(shù)值出棧塘砸,對(duì)其進(jìn)行按位或運(yùn)算节仿,并將結(jié)果壓入棧中
lor 將棧頂兩個(gè) long 類型的數(shù)值出棧,對(duì)其進(jìn)行按位或運(yùn)算掉蔬,并將結(jié)果壓入棧中

按位與命令

助記符 操作數(shù) 含義
iand 將棧頂兩個(gè) int 類型的數(shù)值出棧廊宪,對(duì)其進(jìn)行按位與運(yùn)算,并將結(jié)果壓入棧中
land 將棧頂兩個(gè) long 類型的數(shù)值出棧女轿,對(duì)其進(jìn)行按位與運(yùn)算箭启,并將結(jié)果壓入棧中

按位異或命令

助記符 操作數(shù) 含義
ixor 將棧頂兩個(gè) int 類型的數(shù)值出棧,對(duì)其進(jìn)行按位異或運(yùn)算谈喳,并將結(jié)果壓入棧中
lxor 將棧頂兩個(gè) long 類型的數(shù)值出棧册烈,對(duì)其進(jìn)行按位異或運(yùn)算戈泼,并將結(jié)果壓入棧中

局部變量自增命令

助記符 操作數(shù) 含義
iinc 兩個(gè)婿禽,index 和 const 將第 index 個(gè)(index 從 0 開始計(jì)算)局部變量的數(shù)值加上 const 常量數(shù)值得到結(jié)果

比較命令

助記符 操作數(shù) 含義
lcmp 將棧頂兩個(gè) long 類型的數(shù)值出棧,以第一個(gè)棧頂元素為 value2大猛,第二個(gè)棧頂元素為value1扭倾,如果 value1 - value2 > 0,則將 1 壓入棧中挽绩,如果 value1 - value2 = 0膛壹,則將 0 壓入棧中,如果 value1 - value2 < 0唉堪,則將 -1 壓入棧中
fcmpl 將棧頂兩個(gè) float 類型的數(shù)值出棧模聋,以第一個(gè)棧頂元素為 value2,第二個(gè)棧頂元素為value1唠亚,如果 value1 和 value2 中有一個(gè)值為 NaN链方,則將 -1 壓如棧中;如果 value1 - value2 > 0灶搜,則將 1 壓入棧中祟蚀,如果 value1 - value2 = 0,則將 0 壓入棧中割卖,如果 value1 - value2 < 0前酿,則將 -1 壓入棧中
fcmpg 將棧頂兩個(gè) float 類型的數(shù)值出棧,以第一個(gè)棧頂元素為 value2鹏溯,第二個(gè)棧頂元素為value1罢维,如果 value1 和 value2 中有一個(gè)值為 NaN,則將 1 壓如棧中丙挽;如果 value1 - value2 > 0肺孵,則將 1 壓入棧中攻人,如果 value1 - value2 = 0,則將 0 壓入棧中悬槽,如果 value1 - value2 < 0怀吻,則將 -1 壓入棧中
dcmpl 將棧頂兩個(gè) double 類型的數(shù)值出棧,以第一個(gè)棧頂元素為 value2初婆,第二個(gè)棧頂元素為value1蓬坡,如果 value1 和 value2 中有一個(gè)值為 NaN,則將 -1 壓如棧中磅叛;如果 value1 - value2 > 0屑咳,則將 1 壓入棧中,如果 value1 - value2 = 0弊琴,則將 0 壓入棧中兆龙,如果 value1 - value2 < 0,則將 -1 壓入棧中
dcmpg 將棧頂兩個(gè) double 類型的數(shù)值出棧敲董,以第一個(gè)棧頂元素為 value2紫皇,第二個(gè)棧頂元素為value1,如果 value1 和 value2 中有一個(gè)值為 NaN腋寨,則將 1 壓如棧中聪铺;如果 value1 - value2 > 0,則將 1 壓入棧中萄窜,如果 value1 - value2 = 0铃剔,則將 0 壓入棧中,如果 value1 - value2 < 0查刻,則將 -1 壓入棧中

類型轉(zhuǎn)換命令

java 虛擬機(jī)直接支持?jǐn)?shù)值類型的寬化類型轉(zhuǎn)換命令(即小范圍類型向大范圍類型的安全轉(zhuǎn)換)键兜,這些轉(zhuǎn)換無需顯示的轉(zhuǎn)換命令,當(dāng)然穗泵,也可以用轉(zhuǎn)換命令來要求其進(jìn)行顯示的轉(zhuǎn)換普气。其主要包括以下三種類型

  • int 類型轉(zhuǎn)換到 long、float 或者 double 類型
  • long 類型轉(zhuǎn)換到 float火欧、double 類型
  • float 類型轉(zhuǎn)換到 double 類型

對(duì)于窄轉(zhuǎn)換類型(即大范圍類型向小范圍類型的安全轉(zhuǎn)換)棋电,必須顯示使用轉(zhuǎn)換命令來完成,主要包括以操作

助記符 操作數(shù) 含義
i2b 將棧頂 int 類型數(shù)值出棧苇侵,將其帶符號(hào)轉(zhuǎn)換成 byte 類型數(shù)據(jù)赶盔,并將其結(jié)果壓入操作數(shù)棧。注意:此過程可能導(dǎo)致精度丟失榆浓,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
i2c 將棧頂 int 類型數(shù)值出棧于未,將其帶符號(hào)轉(zhuǎn)換成 char 類型數(shù)據(jù),并將其結(jié)果壓入操作數(shù)棧。注意:此過程可能導(dǎo)致精度丟失烘浦,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
i2s 將棧頂 int 類型數(shù)值出棧狭魂,將其帶符號(hào)轉(zhuǎn)換成 short 類型數(shù)據(jù)寞酿,并將其結(jié)果壓入操作數(shù)棧肮柜。注意:此過程可能導(dǎo)致精度丟失檬嘀,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
l2i 將棧頂 long 類型數(shù)值出棧,將其帶符號(hào)轉(zhuǎn)換成 int 類型數(shù)據(jù)握侧,并將其結(jié)果壓入操作數(shù)棧蚯瞧。注意:此過程可能導(dǎo)致精度丟失,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
l2f 將棧頂 long 類型數(shù)值出棧品擎,將其帶符號(hào)轉(zhuǎn)換成 int 類型數(shù)據(jù)埋合,并將其結(jié)果壓入操作數(shù)棧。注意:此過程可能導(dǎo)致精度丟失萄传,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
l2d 將棧頂 long 類型數(shù)值出棧甚颂,將其帶符號(hào)轉(zhuǎn)換成 double 類型數(shù)據(jù),并將其結(jié)果壓入操作數(shù)棧秀菱。注意:此過程可能導(dǎo)致精度丟失振诬,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
f2i 將棧頂 float 類型數(shù)值出棧,將其帶符號(hào)轉(zhuǎn)換成 int 類型數(shù)據(jù)答朋,并將其結(jié)果壓入操作數(shù)棧贷揽。注意:此過程可能導(dǎo)致精度丟失,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
f2l 將棧頂 float 類型數(shù)值出棧梦碗,將其帶符號(hào)轉(zhuǎn)換成 long 類型數(shù)據(jù),并將其結(jié)果壓入操作數(shù)棧蓖救。注意:此過程可能導(dǎo)致精度丟失洪规,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
f2d 將棧頂 float 類型數(shù)值出棧,將其帶符號(hào)轉(zhuǎn)換成 double 類型數(shù)據(jù)循捺,并將其結(jié)果壓入操作數(shù)棧斩例。注意:此過程可能導(dǎo)致精度丟失,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
d2i 將棧頂 double 類型數(shù)值出棧从橘,將其帶符號(hào)轉(zhuǎn)換成 int 類型數(shù)據(jù)念赶,并將其結(jié)果壓入操作數(shù)棧。注意:此過程可能導(dǎo)致精度丟失恰力,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
d2l 將棧頂 double 類型數(shù)值出棧叉谜,將其帶符號(hào)轉(zhuǎn)換成 long 類型數(shù)據(jù),并將其結(jié)果壓入操作數(shù)棧踩萎。注意:此過程可能導(dǎo)致精度丟失停局,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)
d2f 將棧頂 double 類型數(shù)值出棧,將其帶符號(hào)轉(zhuǎn)換成 float 類型數(shù)據(jù),并將其結(jié)果壓入操作數(shù)棧董栽。注意:此過程可能導(dǎo)致精度丟失码倦,甚至可能導(dǎo)致轉(zhuǎn)換結(jié)果與原先數(shù)值有不同的正負(fù)號(hào)

對(duì)象創(chuàng)建與訪問命令

助記符 操作數(shù) 含義
new 兩個(gè),indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的類創(chuàng)建該類實(shí)例锭碳,并將類引用壓入棧頂
newarray 一個(gè)袁稽,atype 根據(jù) atype 確定要?jiǎng)?chuàng)建的基本數(shù)據(jù)類型,其中 atype的值表示如下:4 表示 boolean擒抛,5 表示 char运提,6 表示 float,7 表示 double闻葵,8 表示 byte民泵,9 表示 short,10 表示 int槽畔,11 表示 long栈妆。然后將棧頂 int 類型的數(shù)值出棧,表示創(chuàng)建數(shù)組的大小厢钧,創(chuàng)建數(shù)組完畢后鳞尔,將數(shù)組的引用值壓入操作數(shù)棧中
anewarray 兩個(gè),indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的類確定創(chuàng)建數(shù)組的類型早直。然后將棧頂 int 類型的數(shù)值出棧寥假,表示創(chuàng)建數(shù)組的大小,創(chuàng)建數(shù)組完畢后霞扬,將數(shù)組的引用值壓入操作數(shù)棧中
getfield 兩個(gè)糕韧,indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的字段確定具體的字段描述信息,然后將棧頂?shù)膶?duì)象引用數(shù)值出棧喻圃,根據(jù)對(duì)象引用和字段描述信息獲取該字段的具體值萤彩,然后壓入棧頂
putfield 兩個(gè),indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的字段確定具體的字段描述信息斧拍,然后將棧頂?shù)臄?shù)值 value 出棧雀扶,再將棧頂?shù)膶?duì)象引用 objectref 出棧,根據(jù)對(duì)象引用和字段描述信息獲取該字段并將其設(shè)置為 value 值
getstatic 兩個(gè)肆汹,indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的字段獲取該字段的具體值愚墓,然后壓入棧頂
putstatic 兩個(gè),indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的字段確定具體的字段描述信息昂勉,然后將棧頂?shù)臄?shù)值 value 出棧浪册,根據(jù)字段描述信息獲取該字段并將其設(shè)置為 value 值
baload 將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo)),再將棧頂?shù)?boolean 或 byte 類型的數(shù)組引用類型 arrayref 出棧硼啤,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素议经,將其具體值壓入棧頂
caload 將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))斧账,再將棧頂?shù)?char 類型的數(shù)組引用類型 arrayref 出棧,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素煞肾,將其具體值壓入棧頂
iaload 將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))咧织,再將棧頂?shù)?int 類型的數(shù)組引用類型 arrayref 出棧,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素籍救,將其具體值壓入棧頂
daload 將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))习绢,再將棧頂?shù)?double 類型的數(shù)組引用類型 arrayref 出棧,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素蝙昙,將其具體值壓入棧頂
aaload 將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))闪萄,再將棧頂?shù)膶?duì)象類型的數(shù)組引用類型 arrayref 出棧,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素奇颠,將其具體值壓入棧頂
bastore 將棧頂?shù)?value 數(shù)值出棧败去,再將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo)),再將棧頂?shù)?boolean 或 byte 類型的數(shù)組引用類型 arrayref 出棧烈拒,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素圆裕,將該元素的值賦為 value 值
castore 將棧頂?shù)?value 數(shù)值出棧,再將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))荆几,再將棧頂?shù)?char 類型的數(shù)組引用類型 arrayref 出棧吓妆,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素,將該元素的值賦為 value 值
iastore 將棧頂?shù)?value 數(shù)值出棧吨铸,再將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))行拢,再將棧頂?shù)?int 類型的數(shù)組引用類型 arrayref 出棧,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素诞吱,將該元素的值賦為 value 值
dastore 將棧頂?shù)?value 數(shù)值出棧舟奠,再將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo)),再將棧頂?shù)?double 類型的數(shù)組引用類型 arrayref 出棧狐胎,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素鸭栖,將該元素的值賦為 value 值
aastore 將棧頂?shù)?value 數(shù)值出棧,再將棧頂?shù)?int 類型數(shù)值 index 出棧(表示數(shù)組的下標(biāo))握巢,再將棧頂?shù)膶?duì)象類型的數(shù)組引用類型 arrayref 出棧,根據(jù) arrayref 和 index 定位到具體的數(shù)組元素松却,將該元素的值賦為 value 值
arraylength 將棧頂?shù)臄?shù)組引用值出棧暴浦,獲取數(shù)組的長度,并將其壓入棧頂
instanceof 兩個(gè)晓锻,indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的類確定具體的類描述信息 class歌焦,然后將棧頂元素 objectref 出棧,檢查 objectref 是否是指定的類 class砚哆,如果是独撇,則將 1 壓入棧頂,否則將 0 壓入棧頂
checkcast 兩個(gè),indexbyte1, indexbyte2 根據(jù)常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量索引指向的類確定具體的類描述信息 class纷铣,然后將棧頂元素 objectref 出棧卵史,檢查 objectref 是否可以轉(zhuǎn)換成指定的類 class,如果可以搜立,則將 objectref 壓入棧頂以躯,否則拋出 ClassCastException 異常

操作數(shù)棧管理命令

助記符 操作數(shù) 含義
pop 將操作數(shù)棧頂元素出棧
pop2 將操作數(shù)棧頂兩個(gè)元素出棧
dup 將操作數(shù)棧頂元素進(jìn)行復(fù)制,然后將復(fù)制值壓入棧頂
dup2 將操作數(shù)棧頂兩個(gè)元素進(jìn)行復(fù)制啄踊,然后按順序?qū)?fù)制值壓入棧頂忧设。具體操作過程如下:將操作數(shù)棧頂元素 value2 出棧,再將棧頂元素 value1 出棧颠通,對(duì) value1 進(jìn)行復(fù)制得到 value1_1址晕,對(duì) value2 復(fù)制得到 value2_1,然后將 value1 入棧顿锰,再將 value2 入棧谨垃,再將 value1_1 入棧,再將 value2_1 入棧
dup_x1 復(fù)制操作數(shù)棧棧頂?shù)闹的於⒉迦氲綏m斠韵?2 個(gè)值之后乘客。具體操作過程如下:將棧頂元素 value2 出棧,復(fù)制 value2 得到 value2_1淀歇,再將棧頂 value1 出棧易核,然后將 value2_1 入棧,再將 value1 入棧浪默,再將 value2 入棧
dup_x2 復(fù)制操作數(shù)棧棧頂?shù)闹的抵保⒉迦氲綏m斠韵?2 個(gè)(次棧頂元素是 long 或 double 類型)或 3 個(gè)(次棧頂元素不是 long 或 double 類型)值之后。具體操作過程如下(以次棧頂元素不是 long 或 double 類型為例):將棧頂元素 value3 出棧纳决,復(fù)制 value3 得到 value3_1碰逸,再將棧頂 value2 出棧,再將棧頂 value1 出棧阔加,然后將 value3_1 入棧饵史,再將 value1 入棧,再將 value2 入棧胜榔,再將 value3 入棧
dup2_x1 dup_x1 的雙倍版本胳喷,即復(fù)制兩個(gè)棧頂元素
dup2_x2 dup_x2 的雙倍版本,即復(fù)制兩個(gè)棧頂元素
swap 將操作數(shù)棧頂?shù)膬蓚€(gè)元素互換

控制轉(zhuǎn)移命令

助記符 操作數(shù) 含義
ifeq 兩個(gè)夭织,branchbyte1, branchbyte2 將棧頂元素出棧吭露,將這個(gè)值與 0 進(jìn)行比較,如果等于 0尊惰,則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令讲竿,否則繼續(xù)執(zhí)行下一條命令
iflt 兩個(gè)泥兰,branchbyte1, branchbyte2 將棧頂元素出棧,將這個(gè)值與 0 進(jìn)行比較题禀,如果小于 0鞋诗,則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
ifne 兩個(gè)投剥,branchbyte1, branchbyte2 將棧頂元素出棧师脂,將這個(gè)值與 0 進(jìn)行比較,如果不等于 0江锨,則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令吃警,否則繼續(xù)執(zhí)行下一條命令
ifge 兩個(gè),branchbyte1, branchbyte2 將棧頂元素出棧啄育,將這個(gè)值與 0 進(jìn)行比較酌心,如果大于或等于 0,則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令挑豌,否則繼續(xù)執(zhí)行下一條命令
ifgt 兩個(gè)安券,branchbyte1, branchbyte2 將棧頂元素出棧,將這個(gè)值與 0 進(jìn)行比較氓英,如果大于 0侯勉,則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
ifle 兩個(gè)铝阐,branchbyte1, branchbyte2 將棧頂元素出棧址貌,將這個(gè)值與 0 進(jìn)行比較,如果小于或等于 0徘键,則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令练对,否則繼續(xù)執(zhí)行下一條命令
ifnull 兩個(gè),branchbyte1, branchbyte2 將棧頂元素出棧吹害,判斷這個(gè)值是否是 null螟凭,如果是 null, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
ifnonnull 兩個(gè)它呀,branchbyte1, branchbyte2 將棧頂元素出棧螺男,判斷這個(gè)值是否是 null,如果不是 null, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令纵穿,否則繼續(xù)執(zhí)行下一條命令
if_icmpeq 兩個(gè)烟号,branchbyte1, branchbyte2 將棧頂元素 value2 出棧,再將棧頂元素 value1 出棧政恍,如果 value1 == values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
if_icmpne 兩個(gè)达传,branchbyte1, branchbyte2 將棧頂元素 value2 出棧篙耗,再將棧頂元素 value1 出棧迫筑,如果 value1 != values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
if_icmplt 兩個(gè)宗弯,branchbyte1, branchbyte2 將棧頂元素 value2 出棧脯燃,再將棧頂元素 value1 出棧,如果 value1 < values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令蒙保,否則繼續(xù)執(zhí)行下一條命令
if_icmpge 兩個(gè)辕棚,branchbyte1, branchbyte2 將棧頂元素 value2 出棧,再將棧頂元素 value1 出棧邓厕,如果 value1 >= values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令逝嚎,否則繼續(xù)執(zhí)行下一條命令
if_icmpgt 兩個(gè),branchbyte1, branchbyte2 將棧頂元素 value2 出棧详恼,再將棧頂元素 value1 出棧补君,如果 value1 > values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
if_icmple 兩個(gè)昧互,branchbyte1, branchbyte2 將棧頂元素 value2 出棧挽铁,再將棧頂元素 value1 出棧,如果 value1 <= values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令敞掘,否則繼續(xù)執(zhí)行下一條命令
if_acmpeq 兩個(gè)叽掘,branchbyte1, branchbyte2 將棧頂對(duì)象引用類型元素 value2 出棧,再將棧頂對(duì)象引用類型元素 value1 出棧玖雁,如果 value1 == values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令更扁,否則繼續(xù)執(zhí)行下一條命令
if_acmpne 兩個(gè),branchbyte1, branchbyte2 將棧頂對(duì)象引用類型元素 value2 出棧茄菊,再將棧頂對(duì)象引用類型元素 value1 出棧疯潭,如果 value1 != values, 則跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令,否則繼續(xù)執(zhí)行下一條命令
goto 兩個(gè)面殖,branchbyte1, branchbyte2 無條件跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令
goto_w 四個(gè)竖哩,branchbyte1, branchbyte2, branchbyte3, branchbyte4 無條件跳轉(zhuǎn)到 ((branchbyte1 << 24) (branchbyte2 << 16) (branchbyte3 << 8) branchbyte4) 位置處執(zhí)行命令
jsr 兩個(gè),branchbyte1, branchbyte2 無條件跳轉(zhuǎn)到 ((branchbyte1 << 8) branchbyte2) 位置處執(zhí)行命令脊僚,并將 jsr 的下一條命令地址壓如棧頂
jsr_w 四個(gè)相叁,branchbyte1, branchbyte2, branchbyte3, branchbyte4 無條件跳轉(zhuǎn)到 ((branchbyte1 << 24) (branchbyte2 << 16) (branchbyte3 << 8) branchbyte4) 位置處執(zhí)行命令,并將 jsr 的下一條命令地址壓如棧頂
ret 一個(gè)辽幌,index 返回本地變量指定的 index 的命令位置(一般與 jsr 或 jsr_w 聯(lián)合使用)增淹。index是一個(gè) 0 ~ 255 之間的無符號(hào)數(shù),它代表一個(gè)當(dāng)前棧幀的局部變量表的索引值乌企,在該索引位置應(yīng)為一個(gè)returnAddress類型的局部變量虑润,命令執(zhí)行后,將該局部變量的值更新到Java虛擬機(jī)的 PC 寄存器中加酵,令進(jìn)程從修改后的位置繼續(xù)執(zhí)行

方法調(diào)用命令

助記符 操作數(shù) 含義
invokevirtual 兩個(gè)拳喻,indexbyte1, indexbyte2 調(diào)用實(shí)例方法哭当。具體操作是:取出常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量的索引對(duì)應(yīng)的方法描述符,依次彈出操作數(shù)棧中的函數(shù)個(gè)數(shù)冗澈,再將棧頂?shù)膶?shí)例引用彈出钦勘,根據(jù)這些信息調(diào)用具體實(shí)例的函數(shù)
invokespecial 兩個(gè),indexbyte1, indexbyte2 調(diào)用超類的構(gòu)造方法亚亲,實(shí)例初始化方法彻采,私有方法。具體操作是:取出常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量的索引對(duì)應(yīng)的方法描述符捌归,依次彈出操作數(shù)棧中的函數(shù)個(gè)數(shù)肛响,再將棧頂?shù)膶?shí)例引用彈出,根據(jù)這些信息調(diào)用具體函數(shù)
invokestatic 兩個(gè)陨溅,indexbyte1, indexbyte2 調(diào)用靜態(tài)方法终惑。具體操作是:取出常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量的索引對(duì)應(yīng)的方法描述符,依次彈出操作數(shù)棧中的函數(shù)個(gè)數(shù)门扇,根據(jù)這些信息調(diào)用具體函數(shù)
invokeinterface 四個(gè)雹有,indexbyte1, indexbyte2, count, 0(第四個(gè)操作數(shù)恒為 0) 調(diào)用接口方法。具體操作是:取出常量池中第 ((indexbyte1 << 8) indexbyte2) 個(gè)(從 1 開始計(jì)數(shù))常量的索引對(duì)應(yīng)的方法描述符臼寄,根據(jù)操作數(shù) count 依次彈出操作數(shù)棧中的函數(shù)個(gè)數(shù)霸奕,根據(jù)這些信息調(diào)用具體函數(shù)
invokedynamic 四個(gè),indexbyte1, indexbyte2, 0, 0(第三個(gè)和第四個(gè)操作數(shù)恒為 0) 調(diào)用動(dòng)態(tài)方法

返回命令

助記符 操作數(shù) 含義
ireturn 從當(dāng)前方法返回 int 類型數(shù)值吉拳,可用于函數(shù)返回類型是 boolean质帅、byte、char留攒、short煤惩、int 的函數(shù)返回命令中
lreturn 從當(dāng)前方法返回 long 類型數(shù)值
freturn 從當(dāng)前方法返回 float 類型數(shù)值
dreturn 從當(dāng)前方法返回 double 類型數(shù)值
areturn 從當(dāng)前方法返回對(duì)象引用
return 從當(dāng)前方法返回 void

異常處理命令

助記符 操作數(shù) 含義
athrow 將棧頂?shù)漠惓伋?/td>

同步命令

助記符 操作數(shù) 含義
monitorenter 將棧頂?shù)囊脤?duì)象出棧,獲取該對(duì)象的鎖炼邀,用于進(jìn)入同步塊
monitorexit 將棧頂?shù)囊脤?duì)象出棧魄揉,釋放該對(duì)象的鎖,用于退出同步塊

invokeinterface 這個(gè)是比較難的一個(gè)指令 最后一個(gè)字節(jié)(操作數(shù)第四個(gè)字節(jié)必須為0 ??)

Operation

Invoke interface method

Format

invokeinterface
indexbyte1
indexbyte2
count
0

Forms

invokeinterface = 185 (0xb9)

Operand Stack

..., objectref, [arg1, [arg2 ...]] →

...

Description

The unsigned indexbyte1 and indexbyte2 are used to construct an index into the run-time constant pool of the current class (§2.6), where the value of the index is (indexbyte1 << 8) | indexbyte2. The run-time constant pool item at that index must be a symbolic reference to an interface method (§5.1), which gives the name and descriptor (§4.3.3) of the interface method as well as a symbolic reference to the interface in which the interface method is to be found. The named interface method is resolved (§5.4.3.4).

The resolved interface method must not be an instance initialization method, or the class or interface initialization method (§2.9).

The count operand is an unsigned byte that must not be zero. The objectref must be of type reference and must be followed on the operand stack by nargs argument values, where the number, type, and order of the values must be consistent with the descriptor of the resolved interface method. The value of the fourth operand byte must always be zero.

Let C be the class of objectref. The actual method to be invoked is selected by the following lookup procedure:

  1. If C contains a declaration for an instance method with the same name and descriptor as the resolved method, then it is the method to be invoked.

  2. Otherwise, if C has a superclass, a search for a declaration of an instance method with the same name and descriptor as the resolved method is performed, starting with the direct superclass of C and continuing with the direct superclass of that class, and so forth, until a match is found or no further superclasses exist. If a match is found, then it is the method to be invoked.

  3. Otherwise, if there is exactly one maximally-specific method (§5.4.3.3) in the superinterfaces of C that matches the resolved method's name and descriptor and is not abstract, then it is the method to be invoked.

If the method is synchronized, the monitor associated with objectref is entered or reentered as if by execution of a monitorenter instruction (§monitorenter) in the current thread.

If the method is not native, the nargs argument values and objectref are popped from the operand stack. A new frame is created on the Java Virtual Machine stack for the method being invoked. The objectref and the argument values are consecutively made the values of local variables of the new frame, with objectref in local variable 0, arg1 in local variable 1 (or, if arg1 is of type long or double, in local variables 1 and 2), and so on. Any argument value that is of a floating-point type undergoes value set conversion (§2.8.3) prior to being stored in a local variable. The new frame is then made current, and the Java Virtual Machine pc is set to the opcode of the first instruction of the method to be invoked. Execution continues with the first instruction of the method.

If the method is native and the platform-dependent code that implements it has not yet been bound (§5.6) into the Java Virtual Machine, that is done. The nargs argument values and objectref are popped from the operand stack and are passed as parameters to the code that implements the method. Any argument value that is of a floating-point type undergoes value set conversion (§2.8.3) prior to being passed as a parameter. The parameters are passed and the code is invoked in an implementation-dependent manner. When the platform-dependent code returns:

  • If the native method is synchronized, the monitor associated with objectref is updated and possibly exited as if by execution of a monitorexit instruction (§monitorexit) in the current thread.

  • If the native method returns a value, the return value of the platform-dependent code is converted in an implementation-dependent way to the return type of the native method and pushed onto the operand stack.

Linking Exceptions

During resolution of the symbolic reference to the interface method, any of the exceptions pertaining to interface method resolution (§5.4.3.4) can be thrown.

Otherwise, if the resolved method is static or private, the invokeinterface instruction throws an IncompatibleClassChangeError.

Run-time Exceptions

Otherwise, if objectref is null, the invokeinterface instruction throws a NullPointerException.

Otherwise, if the class of objectref does not implement the resolved interface, invokeinterface throws an IncompatibleClassChangeError.

Otherwise, if step 1 or step 2 of the lookup procedure selects a method that is not public, invokeinterface throws an IllegalAccessError.

Otherwise, if step 1 or step 2 of the lookup procedure selects an abstract method, invokeinterface throws an AbstractMethodError.

Otherwise, if step 1 or step 2 of the lookup procedure selects a native method and the code that implements the method cannot be bound, invokeinterface throws an UnsatisfiedLinkError.

Otherwise, if step 3 of the lookup procedure determines there are multiple maximally-specific methods in the superinterfaces of C that match the resolved method's name and descriptor and are not abstract, invokeinterface throws an IncompatibleClassChangeError

Otherwise, if step 3 of the lookup procedure determines there are zero maximally-specific methods in the superinterfaces of C that match the resolved method's name and descriptor and are not abstract, invokeinterface throws an AbstractMethodError.

Notes

The count operand of the invokeinterface instruction records a measure of the number of argument values, where an argument value of type long or type double contributes two units to the count value and an argument of any other type contributes one unit. This information can also be derived from the descriptor of the selected method. The redundancy is historical.

The fourth operand byte exists to reserve space for an additional operand used in certain of Oracle's Java Virtual Machine implementations, which replace the invokeinterface instruction by a specialized pseudo-instruction at run time. It must be retained for backwards compatibility.

The nargs argument values and objectref are not one-to-one with the first nargs+1 local variables. Argument values of types long and double must be stored in two consecutive local variables, thus more than nargs local variables may be required to pass nargs argument values to the invoked method.

The selection logic allows a non-abstract method declared in a superinterface to be selected. Methods in interfaces are only considered if there is no matching method in the class hierarchy. In the event that there are two non-abstract methods in the superinterface hierarchy, with neither more specific than the other, an error occurs; there is no attempt to disambiguate (for example, one may be the referenced method and one may be unrelated, but we do not prefer the referenced method). On the other hand, if there are many abstract methods but only one non-abstract method, the non-abstract method is selected (unless an abstract method is more specific).

備注

 count記錄了參數(shù)的個(gè)數(shù)拭宁,一個(gè)long或者double類型的參數(shù)記2洛退,其余的參數(shù)記1,這個(gè)信息也可以從解析出的方法描述符中得到杰标,放在這里是由于歷史原因兵怯。

第四個(gè)運(yùn)算字節(jié)(必須為0的)的存在是為額外的運(yùn)算元預(yù)留空間,這些運(yùn)算元用于某些oracle的java虛擬機(jī)腔剂,用來在運(yùn)行時(shí)用某些專用的偽指令替換invokeinterface指令媒区。因此必須保留以達(dá)到后項(xiàng)兼容性。

nargs個(gè)參數(shù)并不一定就對(duì)應(yīng)nargs個(gè)局部變量,對(duì)于long或double類型的參數(shù)值就需要連續(xù)兩個(gè)局部變量的位置來存儲(chǔ)驻仅,這時(shí)谅畅,nargs個(gè)參數(shù)的傳遞就需要多于nargs個(gè)的局部變量位置。

在2006年的JavaOne大會(huì)上噪服,Sun公司宣布最終會(huì)把Java開源,并在隨后的一年胜茧,陸續(xù)將JDK的各個(gè)部分(其中當(dāng)然也包括了HotSpot VM)在GPL協(xié)議下公開了源碼粘优, 并在此基礎(chǔ)上建立了OpenJDK。這樣呻顽,HotSpot VM便成為了Sun JDK和OpenJDK兩個(gè)實(shí)現(xiàn)極度接近的JDK項(xiàng)目的共同虛擬機(jī)雹顺。

在2008年和2009年,Oracle公司分別收購了BEA公司和Sun公司廊遍,這樣Oracle就同時(shí)擁有了兩款優(yōu)秀的Java虛擬機(jī):JRockit VM和HotSpot VM嬉愧。 Oracle公司宣布在不久的將來(大約應(yīng)在發(fā)布JDK 8的時(shí)候)會(huì)完成這兩款虛擬機(jī)的整合工作,使之優(yōu)勢(shì)互補(bǔ)喉前。 整合的方式大致上是在HotSpot的基礎(chǔ)上没酣,移植JRockit的優(yōu)秀特性,譬如使用JRockit的垃圾回收器與MissionControl服務(wù)卵迂, 使用HotSpot的JIT編譯器與混合的運(yùn)行時(shí)系統(tǒng)裕便。

JDK中rt.jar、tools.jar和dt.jar作用

dt.jar和tools.jar位于:{Java_Home}/lib/下见咒,而rt.jar位于:{Java_Home}/jre/lib/下,其中:

rt.jar是JAVA基礎(chǔ)類庫偿衰,也就是你在java doc里面看到的所有的類的class文件
dt.jar是關(guān)于運(yùn)行環(huán)境的類庫

tools.jar是工具類庫,編譯和運(yùn)行需要的都是toos.jar里面的類分別是sun.tools.java.; sun.tols.javac.;

在Classpath設(shè)置這幾個(gè)變量,是為了方便在程序中 import改览;Web系統(tǒng)都用到tool.jar下翎。

1. rt.jar
rt.jar 默認(rèn)就在Root Classloader的加載路徑里面的,而在Claspath配置該變量是不需要的宝当;同時(shí)jre/lib目錄下的

其他jar:jce.jar视事、jsse.jar、charsets.jar今妄、resources.jar都在Root Classloader中

2. tools.jar

tools.jar 是系統(tǒng)用來編譯一個(gè)類的時(shí)候用到的郑口,即執(zhí)行javac的時(shí)候用到

javac XXX.java

實(shí)際上就是運(yùn)行

java -Calsspath=%JAVA_HOME%\lib\tools.jar xx.xxx.Main XXX.java

javac就是對(duì)上面命令的封裝 所以tools.jar 也不用加到classpath里面

3. dt.jar
dt.jar是關(guān)于運(yùn)行環(huán)境的類庫,主要是swing的包 在用到swing時(shí)最好加上。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末盾鳞,一起剝皮案震驚了整個(gè)濱河市犬性,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腾仅,老刑警劉巖乒裆,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異推励,居然都是意外死亡鹤耍,警方通過查閱死者的電腦和手機(jī)肉迫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來稿黄,“玉大人喊衫,你說我怎么就攤上這事「伺拢” “怎么了族购?”我有些...
    開封第一講書人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長陵珍。 經(jīng)常有香客問我寝杖,道長,這世上最難降的妖魔是什么互纯? 我笑而不...
    開封第一講書人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任瑟幕,我火速辦了婚禮,結(jié)果婚禮上留潦,老公的妹妹穿的比我還像新娘只盹。我一直安慰自己,他們只是感情好愤兵,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開白布鹿霸。 她就那樣靜靜地躺著,像睡著了一般秆乳。 火紅的嫁衣襯著肌膚如雪懦鼠。 梳的紋絲不亂的頭發(fā)上塑娇,一...
    開封第一講書人閱讀 50,096評(píng)論 1 291
  • 那天伸眶,我揣著相機(jī)與錄音,去河邊找鬼突诬。 笑死扯键,一個(gè)胖子當(dāng)著我的面吹牛睦袖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荣刑,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼馅笙,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了厉亏?” 一聲冷哼從身側(cè)響起董习,我...
    開封第一講書人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎爱只,沒想到半個(gè)月后皿淋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年窝趣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疯暑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡哑舒,死狀恐怖妇拯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情散址,我是刑警寧澤乖阵,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站预麸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏儒将。R本人自食惡果不足惜吏祸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望钩蚊。 院中可真熱鬧贡翘,春花似錦、人聲如沸砰逻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝠咆。三九已至踊东,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間刚操,已是汗流浹背闸翅。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留菊霜,地道東北人坚冀。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像鉴逞,于是被迫代替她去往敵國和親记某。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容