亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java字節(jié)碼指令集的使用詳細(xì)

 更新時(shí)間:2013年05月04日 13:17:04   作者:  
本篇文章對(duì)Java字節(jié)碼指令集的使用進(jìn)行了詳細(xì)的介紹。需要的朋友參考下
    Java虛擬機(jī)指令由一個(gè)字節(jié)長(zhǎng)度的、代表某種特定含義的操作碼(Opcode)以及其后的零個(gè)至多個(gè)代表此操作參數(shù)的操作數(shù)構(gòu)成。虛擬機(jī)中許多指令并不包含操作數(shù),只有一個(gè)操作碼。若忽略異常,JVM解釋器使用一下為代碼即可有效工作。
復(fù)制代碼 代碼如下:

do{
    自動(dòng)計(jì)算PC寄存器以及從PC寄存器的位置取出操作碼
    if(存在操作數(shù)) 取出操作數(shù);
    執(zhí)行操作碼所定義的操作;
}while(處理下一次循環(huán))

操作數(shù)的數(shù)量以及長(zhǎng)度,取決于操作碼,若一個(gè)操作數(shù)長(zhǎng)度超過(guò)了一個(gè)字節(jié),將會(huì)以Big-Endian順序存儲(chǔ)(高位在前字節(jié)碼),其值應(yīng)為(byte1<<8)|byte2。

    字節(jié)碼指令流是單字節(jié)對(duì)齊,只有"tableswitch"和"lookupswitch"兩指令例外,它們的操作數(shù)比較特殊,以4字節(jié)為界限劃分的,需要預(yù)留出相應(yīng)的空位來(lái)實(shí)現(xiàn)對(duì)齊。

    限制Java虛擬機(jī)操作碼的長(zhǎng)度為一個(gè)字節(jié),且放棄編譯后代碼的參數(shù)長(zhǎng)度對(duì)齊,是為了獲得短小精干的編譯代碼,即使可能會(huì)讓JVM實(shí)現(xiàn)付出一定性能成本為代價(jià)。由于操作碼只能有一個(gè)字節(jié)長(zhǎng)度,故限制了指令集的數(shù)量,又沒有假設(shè)數(shù)據(jù)是對(duì)齊好的,意味著數(shù)據(jù)超過(guò)一個(gè)字節(jié)時(shí),不得不從字節(jié)中重建出具體的數(shù)據(jù)結(jié)構(gòu),會(huì)損失一些性能。

數(shù)據(jù)類型與Java虛擬機(jī)

    在JVM中的指令集中,大多數(shù)指令包含了其操作對(duì)應(yīng)的數(shù)據(jù)類型信息。如iload指令從局部變量表中加載int型的數(shù)據(jù)到操作數(shù)棧中,而fload加載的是float類型的數(shù)據(jù)。

    對(duì)于大部分與數(shù)據(jù)類型相關(guān)的字節(jié)碼指令,他們的操作碼助記符都有特殊的字符來(lái)表明:i代表int類型,l代表long,s代表short,b代表 byte,c代表char,f代表float,d代表double,a代表reference。有一些單獨(dú)指令可以在必要的時(shí)候用來(lái)將一些不不支持的類型轉(zhuǎn)換為可被支持的類型。

加載和存儲(chǔ)指令

    加載和存儲(chǔ)指令用于將數(shù)據(jù)從棧幀的局部變量表和操作數(shù)棧之間來(lái)回傳輸。
    1)將一個(gè)局部變量加載到操作數(shù)棧的指令包括:iload,iload_<n>,lload、lload_<n>、float、 fload_<n>、dload、dload_<n>,aload、aload_<n>。
    2)將一個(gè)數(shù)值從操作數(shù)棧存儲(chǔ)到局部變量標(biāo)的指令:istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
    3)將常量加載到操作數(shù)棧的指令:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_<i>,lconst_<l>,fconst_<f>,dconst_<d>
    4)局部變量表的訪問索引指令:wide
    一部分以尖括號(hào)結(jié)尾的指令代表了一組指令,如iload_<i>,代表了iload_0,iload_1等,這幾組指令都是帶有一個(gè)操作數(shù)的通用指令。

運(yùn)算指令

    算術(shù)指令用于對(duì)兩個(gè)操作數(shù)棧上的值進(jìn)行某種特定運(yùn)算,并把結(jié)果重新存入到操作棧頂。
    1)加法指令:iadd,ladd,fadd,dadd
    2)減法指令:isub,lsub,fsub,dsub
    3)乘法指令:imul,lmul,fmul,dmul
    4)除法指令:idiv,ldiv,fdiv,ddiv
    5)求余指令:irem,lrem,frem,drem
    6)取反指令:ineg,leng,fneg,dneg
    7)位移指令:ishl,ishr,iushr,lshl,lshr,lushr
    8)按位或指令:ior,lor
    9)按位與指令:iand,land
    10)按位異或指令:ixor,lxor
    11)局部變量自增指令:iinc
    12)比較指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp

    Java虛擬機(jī)沒有明確規(guī)定整型數(shù)據(jù)溢出的情況,但規(guī)定了處理整型數(shù)據(jù)時(shí),只有除法和求余指令出現(xiàn)除數(shù)為0時(shí)會(huì)導(dǎo)致虛擬機(jī)拋出異常。

加載和存儲(chǔ)指令

    加載和存儲(chǔ)指令用于將數(shù)據(jù)從哦你哦過(guò)棧幀的局部變量表和操作數(shù)棧之間來(lái)回傳輸。

    1)將一個(gè)局部變量加載到操作數(shù)棧的指令包括:iload,iload_<n>,lload、lload_<n>、float、 fload_<n>、dload、dload_<n>,aload、aload_<n>。
    2)將一個(gè)數(shù)值從操作數(shù)棧存儲(chǔ)到局部變量標(biāo)的指令:istore,istore_<n>,lstore,lstore_<n>,fstore,fstore_<n>,dstore,dstore_<n>,astore,astore_<n>
    3)將常量加載到操作數(shù)棧的指令:bipush,sipush,ldc,ldc_w,ldc2_w,aconst_null,iconst_ml,iconst_<i>,lconst_<l>,fconst_<f>,dconst_<d>
    4)局部變量表的訪問索引指令:wide
    一部分以尖括號(hào)結(jié)尾的指令代表了一組指令,如iload_<i>,代表了iload_0,iload_1等,這幾組指令都是帶有一個(gè)操作數(shù)的通用指令。

運(yùn)算指令

    算術(shù)指令用于對(duì)兩個(gè)操作數(shù)棧上的值進(jìn)行某種特定運(yùn)算,并把結(jié)果重新存入到操作棧頂。
    1)加法指令:iadd,ladd,fadd,dadd
    2)減法指令:isub,lsub,fsub,dsub
    3)乘法指令:imul,lmul,fmul,dmul
    4)除法指令:idiv,ldiv,fdiv,ddiv
    5)求余指令:irem,lrem,frem,drem
    6)取反指令:ineg,leng,fneg,dneg
    7)位移指令:ishl,ishr,iushr,lshl,lshr,lushr
    8)按位或指令:ior,lor
    9)按位與指令:iand,land
    10)按位異或指令:ixor,lxor
    11)局部變量自增指令:iinc
    12)比較指令:dcmpg,dcmpl,fcmpg,fcmpl,lcmp

    Java虛擬機(jī)沒有明確規(guī)定整型數(shù)據(jù)溢出的情況,但規(guī)定了處理整型數(shù)據(jù)時(shí),只有除法和求余指令出現(xiàn)除數(shù)為0時(shí)會(huì)導(dǎo)致虛擬機(jī)拋出異常。

類型轉(zhuǎn)換指令

    類型轉(zhuǎn)換指令將兩種Java虛擬機(jī)數(shù)值類型相互轉(zhuǎn)換,這些操作一般用于實(shí)現(xiàn)用戶代碼的顯式類型轉(zhuǎn)換操作。
    JVM支持寬化類型轉(zhuǎn)換(小范圍類型向大范圍類型轉(zhuǎn)換):
    1)int類型到long,float,double類型
    2)long類型到float,double類型
    3)float到double類型

    窄花類型轉(zhuǎn)換指令:i2b,i2c,i2s,l2i,f2i,f2l,d2l和d2f,窄化類型轉(zhuǎn)換可能會(huì)導(dǎo)致轉(zhuǎn)換結(jié)果產(chǎn)生不同的正負(fù)號(hào),不同數(shù)量級(jí),轉(zhuǎn)換過(guò)程可能會(huì)導(dǎo)致數(shù)值丟失精度。如int或long類型轉(zhuǎn)化整數(shù)類型T時(shí),轉(zhuǎn)換過(guò)程是僅僅丟棄最低位N個(gè)字節(jié)意外的內(nèi)容(N是類型T的數(shù)據(jù)類型長(zhǎng)度)

對(duì)象創(chuàng)建與操作

    雖然類實(shí)例和數(shù)組都是對(duì)象,Java虛擬機(jī)對(duì)類實(shí)例和數(shù)組的創(chuàng)建與操作使用了不同的字節(jié)碼指令。
    1)創(chuàng)建實(shí)例的指令:new
    2)創(chuàng)建數(shù)組的指令:newarray,anewarray,multianewarray
    3)訪問字段指令:getfield,putfield,getstatic,putstatic
    4)把數(shù)組元素加載到操作數(shù)棧指令:baload,caload,saload,iaload,laload,faload,daload,aaload
    5)將操作數(shù)棧的數(shù)值存儲(chǔ)到數(shù)組元素中執(zhí)行:bastore,castore,castore,sastore,iastore,fastore,dastore,aastore
    6)取數(shù)組長(zhǎng)度指令:arraylength
    7)檢查實(shí)例類型指令:instanceof,checkcast

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

    直接操作操作數(shù)棧的指令:pop,pop2,dup,dup2,dup_x1,dup2_x1,dup_x2,dup2_x2和swap
控制轉(zhuǎn)移指令

    讓JVM有條件或無(wú)條件從指定指令而不是控制轉(zhuǎn)移指令的下一條指令繼續(xù)執(zhí)行程序。控制轉(zhuǎn)移指令包括:
    1)條件分支:ifeq,iflt,ifle,ifne,ifgt,ifge,ifnull,ifnotnull,if_cmpeq,if_icmpne,if_icmlt,if_icmpgt等

    2)復(fù)合條件分支:tableswitch,lookupswitch

    3)無(wú)條件分支:goto,goto_w,jsr,jsr_w,ret

    JVM中有專門的指令集處理int和reference類型的條件分支比較操作,為了可以無(wú)明顯標(biāo)示一個(gè)實(shí)體值是否是null,有專門的指令檢測(cè)null 值。boolean類型和byte類型,char類型和short類型的條件分支比較操作,都使用int類型的比較指令完成,而 long,float,double條件分支比較操作,由相應(yīng)類型的比較運(yùn)算指令,運(yùn)算指令會(huì)返回一個(gè)整型值到操作數(shù)棧中,隨后再執(zhí)行int類型的條件比較操作完成整個(gè)分支跳轉(zhuǎn)。各種類型的比較都最終會(huì)轉(zhuǎn)化為int類型的比較操作。

方法調(diào)用和返回指令

    invokevirtual指令:調(diào)用對(duì)象的實(shí)例方法,根據(jù)對(duì)象的實(shí)際類型進(jìn)行分派(虛擬機(jī)分派)。
    invokeinterface指令:調(diào)用接口方法,在運(yùn)行時(shí)搜索一個(gè)實(shí)現(xiàn)這個(gè)接口方法的對(duì)象,找出合適的方法進(jìn)行調(diào)用。
    invokespecial:調(diào)用需要特殊處理的實(shí)例方法,包括實(shí)例初始化方法,私有方法和父類方法
    invokestatic:調(diào)用類方法(static)
    方法返回指令是根據(jù)返回值的類型區(qū)分的,包括ireturn(返回值是boolean,byte,char,short和 int),lreturn,freturn,drturn和areturn,另外一個(gè)return供void方法,實(shí)例初始化方法,類和接口的類初始化i 方法使用。

同步

    JVM支持方法級(jí)同步和方法內(nèi)部一段指令序列同步,這兩種都是通過(guò)moniter實(shí)現(xiàn)的。

    方法級(jí)的同步是隱式的,無(wú)需通過(guò)字節(jié)碼指令來(lái)控制,它實(shí)現(xiàn)在方法調(diào)用和返回操作中。虛擬機(jī)從方法常量池中的方法標(biāo)結(jié)構(gòu)中的 ACC_SYNCHRONIZED標(biāo)志區(qū)分是否是同步方法。方法調(diào)用時(shí),調(diào)用指令會(huì)檢查該標(biāo)志是否被設(shè)置,若設(shè)置,執(zhí)行線程持有moniter,然后執(zhí)行方法,最后完成方法時(shí)釋放moniter。

    同步一段指令集序列,通常由synchronized塊標(biāo)示,JVM指令集中有monitorenter和monitorexit來(lái)支持synchronized語(yǔ)義。

    結(jié)構(gòu)化鎖定是指方法調(diào)用期間每一個(gè)monitor退出都與前面monitor進(jìn)入相匹配的情形。JVM通過(guò)以下兩條規(guī)則來(lái)保證結(jié)結(jié)構(gòu)化鎖成立(T代表一線程,M代表一個(gè)monitor):

    1)T在方法執(zhí)行時(shí)持有M的次數(shù)必須與T在方法完成時(shí)釋放的M次數(shù)相等

    2)任何時(shí)刻都不會(huì)出現(xiàn)T釋放M的次數(shù)比T持有M的次數(shù)多的情況

相關(guān)文章

最新評(píng)論