虛擬機(jī)類(lèi)加載機(jī)制(三)--- 字節(jié)碼指令

Java的技術(shù)體系包括

  • 支持Java程序運(yùn)行的虛擬機(jī)(JVM)
  • 提供接口支持的Java API
  • Java 編程語(yǔ)言
  • 第三方Java框架(如Spring等)

代碼編譯的結(jié)果從本地機(jī)器碼轉(zhuǎn)變?yōu)樽止?jié)碼谭贪,是存儲(chǔ)格式發(fā)展的一小步俯画,確實(shí)編程語(yǔ)言的一大步。


java代碼經(jīng)過(guò)編譯器編譯后玉罐,類(lèi)中方法體內(nèi)的代碼邏輯會(huì)被編譯為一行行虛擬機(jī)能夠識(shí)別的指令,而java虛擬機(jī)規(guī)范中通過(guò)一個(gè)字節(jié)來(lái)存儲(chǔ)所有的虛擬機(jī)指令明也,因此我們將這種指令集稱之為字節(jié)碼指令铭段。

字節(jié)碼指令的含義

字節(jié)碼指令是指,由一個(gè)字節(jié)長(zhǎng)度來(lái)表示胧华,代表著特定含義的數(shù)字(稱之為操作碼)所構(gòu)成的指令寄症,其后有可能跟隨一個(gè)或者多個(gè)此命令所需要的參數(shù)(稱之為操作數(shù))宙彪。大多數(shù)的字節(jié)碼指令都是不包含操作數(shù)的,只存在一個(gè)操作碼有巧。

字節(jié)碼指令的優(yōu)勢(shì)在于释漆,由于不需要操作數(shù)長(zhǎng)度對(duì)齊,所以可以節(jié)省很多用于操作數(shù)對(duì)齊而帶來(lái)的填充和間隔符號(hào)所占用的空間篮迎。同時(shí)一個(gè)字節(jié)的長(zhǎng)度來(lái)代表操作碼男图,從設(shè)計(jì)的初衷我們就能看出視為了盡可能獲得短小的編譯代碼。而這樣的設(shè)計(jì)初衷也是由java語(yǔ)言為了盡可能追求在小數(shù)據(jù)量和高傳輸效率的場(chǎng)景中發(fā)揮優(yōu)勢(shì)所決定的甜橱。

它的劣勢(shì)同樣十分明顯享言,由于一個(gè)字節(jié)所能代表的取值范圍為0~255,這就意味著操作碼最多只能有256個(gè)渗鬼。同時(shí)由于沒(méi)有操作數(shù)長(zhǎng)度對(duì)齊览露,當(dāng)操作碼需要處理的數(shù)據(jù)大于一個(gè)字節(jié)的長(zhǎng)度的時(shí)候,比如要存儲(chǔ)一個(gè)16位長(zhǎng)度的數(shù)據(jù)譬胎,那需要兩個(gè)字節(jié)來(lái)存儲(chǔ)差牛,并且必須在運(yùn)行時(shí)通過(guò)某種規(guī)則還原出原始的數(shù)據(jù)。這樣的操作會(huì)導(dǎo)致字節(jié)碼在執(zhí)行的時(shí)候必然會(huì)損耗一些性能堰乔。

分類(lèi)

字節(jié)碼指令按照用途偏化,大致可以分為9類(lèi)

  1. 加載和存儲(chǔ)指令
  2. 運(yùn)算指令
  3. 類(lèi)型轉(zhuǎn)換指令
  4. 對(duì)象創(chuàng)建與訪問(wèn)指令
  5. 操作數(shù)棧管理指令
  6. 控制轉(zhuǎn)移指令
  7. 方法調(diào)用和返回指令
  8. 異常處理指令
  9. 同步指令

加載和存儲(chǔ)指令

加載和存儲(chǔ)指令用于將數(shù)據(jù)在棧幀中的局部變量表和操作數(shù)棧之間來(lái)回傳輸,這些指令包括如下

  • 將一個(gè)局部變量加載到操作數(shù)棧:iload, iload_<n>, lload, lload<n>, fload, fload_<n>, dload, dload_<n>, aload, aload_<n>
  • 將一個(gè)數(shù)值從操作數(shù)棧存儲(chǔ)到局部變量表:istore, istore_<n>, lstore, lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>
  • 將一個(gè)常量加載到操作數(shù)棧:bipush, sipush, ldc, ldc_w, ldc2_w, aconst_null, iconst_ml, iconst_<i>, lconst_<l>, fconst_<f>, dconst_<d>
  • 擴(kuò)充局部變量表的訪問(wèn)索引的指令:wide

運(yùn)算指令

運(yùn)算指令用于將兩個(gè)操作數(shù)棧上的值進(jìn)行某種特定的運(yùn)算镐侯,并把結(jié)果重新存入到操作數(shù)棧頂侦讨。算數(shù)指令大體可以分為兩種:對(duì)整型數(shù)據(jù)進(jìn)行運(yùn)算的指令,和對(duì)浮點(diǎn)型數(shù)據(jù)進(jìn)行運(yùn)算的指令苟翻。

  • 加法指令: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

虛擬機(jī)規(guī)范中規(guī)定韵卤,在運(yùn)算指令時(shí),只有在除法指令或者求余指令中當(dāng)除數(shù)為0的時(shí)候崇猫,會(huì)拋出ArithmeticException沈条,其余任何場(chǎng)景即使出現(xiàn)溢出,也不會(huì)產(chǎn)生任何運(yùn)行時(shí)異常

類(lèi)型轉(zhuǎn)換指令

類(lèi)型轉(zhuǎn)換指令可以將兩種不同數(shù)值類(lèi)進(jìn)行相互轉(zhuǎn)換诅炉。java虛擬機(jī)直接支持以下類(lèi)型的寬化類(lèi)型轉(zhuǎn)換

  • int -> long float double
  • long -> folat double
  • float -> double
    對(duì)于處理窄化類(lèi)型轉(zhuǎn)換時(shí)蜡歹,必須顯式地使用轉(zhuǎn)換指令來(lái)完成。這些指令包括:i2b, i2c, i2s, f2i, f2l, d2i, d2l, d2f涕烧。數(shù)據(jù)類(lèi)型窄化處理可能會(huì)出現(xiàn)溢出和精度丟失等問(wèn)題月而,但是java虛擬機(jī)規(guī)范中規(guī)定,數(shù)值窄化處理不會(huì)拋出任何運(yùn)行時(shí)異常议纯。

對(duì)象創(chuàng)建與訪問(wèn)指令

雖然在java語(yǔ)言層面父款,類(lèi)實(shí)例和數(shù)組都是對(duì)象,但是虛擬機(jī)對(duì)類(lèi)實(shí)例和數(shù)組的創(chuàng)建和訪問(wèn)使用的是不同的指令,這是因?yàn)樗麄兊膭?chuàng)建過(guò)程是不同的铛漓。指令如下

  • 創(chuàng)建類(lèi)實(shí)例的指令:new
  • 創(chuàng)建數(shù)組是的指令:newarray, anewarray,multianewarray
  • 訪問(wèn)類(lèi)變量和實(shí)例變量:getfield, putfield, getstatic, putstatic
  • 把一個(gè)數(shù)組元素加載到操作數(shù)棧的指令:baload, caload, saload, iaload, laload, faload, daload, aaload
  • 把一個(gè)操作數(shù)棧的值存儲(chǔ)到數(shù)組元素中的指令:bastore, castore, sastore, iastore, fastore, dastore, aastore
  • 取數(shù)組長(zhǎng)度指令:arraylength
  • 檢查類(lèi)實(shí)例類(lèi)型的指令:instanceof, checkcast

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

  • 將操作數(shù)棧的棧頂一個(gè)或者兩個(gè)元素出棧:pop, pop2
  • 復(fù)制棧頂一個(gè)或者兩個(gè)數(shù)值溯香,并將復(fù)制值或雙份的復(fù)制值重新壓入棧頂:dup, dup2, dup_1, dup2_1, dup_2, dup2_2
  • 將棧最頂端的兩個(gè)數(shù)值互換:swap

控制轉(zhuǎn)移指令

控制轉(zhuǎn)移指令可以讓虛擬機(jī)有條件或者無(wú)條件地從指定位置繼續(xù)執(zhí)行程序鲫构。指令如下

  • 條件分支:ifeq, iflt, ifle, ifgt, ifge, ifnull, ifnonnull, if_icmpeq, if_icmpne, if_icmplt, if_icmpgt, if_icacmpeq, if_acmpne
  • 復(fù)合條件分支:tableswitch, lookupswitch
  • 無(wú)條件分支:goto, goto_w, jsr, jsr_w, ret

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

  • invokevirtual, 用于調(diào)用對(duì)象的實(shí)例方法浓恶,根據(jù)對(duì)象的實(shí)際類(lèi)型進(jìn)行分派
  • invokeinterface, 用于調(diào)用接口方法,它會(huì)在運(yùn)行時(shí)搜索一個(gè)實(shí)現(xiàn)了這個(gè)接口方法的對(duì)象结笨,找出適合的方法進(jìn)行調(diào)用
  • invokespecial, 用于調(diào)用一些需要特殊處理的實(shí)例方法包晰,包括實(shí)例初始化方法、私有方法炕吸、父類(lèi)方法
  • invokestatic, 用于調(diào)用類(lèi)方法(static方法)
  • invokedynamic, 用于在運(yùn)行時(shí)動(dòng)態(tài)解析出調(diào)用點(diǎn)限定符所引用的方法伐憾,并執(zhí)行該方法。
  • 方法返回指令:return, ireturn, lreturn, freturn, dreturn, areturn

異常處理指令

java程序中赫模,顯式拋出異常的操作都是由athrow指令來(lái)實(shí)現(xiàn)树肃。除此之外,虛擬機(jī)規(guī)范還規(guī)定了許多運(yùn)行時(shí)異常會(huì)由虛擬機(jī)自動(dòng)拋出瀑罗。

同步指令

java虛擬機(jī)可以支持方法級(jí)的同步和方法內(nèi)部一段指令序列的同步胸嘴,都是使用管程(Monitor)來(lái)支持。方法級(jí)的同步是隱式的斩祭,無(wú)需通過(guò)字節(jié)碼指令來(lái)控制劣像,因?yàn)橥ㄟ^(guò)方法常量池的方法表結(jié)構(gòu)中的 ACC_SYNCHRONIZED 訪問(wèn)標(biāo)志可以得知一個(gè)方法是否聲明為同步方法。方法內(nèi)部的同步則是通過(guò) monitorenter 和 monitorexit 兩條指令來(lái)完成摧玫。編譯器需要確保耳奕,方法中調(diào)用過(guò)的每條 monitorenter 指令都必須執(zhí)行其對(duì)應(yīng)的 monitorexit指令。

總結(jié)

Java虛擬機(jī)規(guī)范規(guī)定了Java虛擬機(jī)應(yīng)共同遵守的存儲(chǔ)格式:Class文件格式字節(jié)碼指令集诬像。Class文件結(jié)構(gòu)從虛擬機(jī)規(guī)范發(fā)布以來(lái)屋群,java的技術(shù)體系發(fā)生了很多很多的變化,包括語(yǔ)言坏挠,API等有了極大的發(fā)展和很多的變化谓晌。但Class文件結(jié)構(gòu)一直處于比較穩(wěn)定的狀態(tài),它的主體結(jié)構(gòu)癞揉、字節(jié)碼指令都幾乎沒(méi)有什么大的變化纸肉。這也說(shuō)明了反應(yīng)出虛擬機(jī)的具體實(shí)現(xiàn)和上層的使用之間的耦合性很低,靈活性很大喊熟。

虛擬機(jī)加類(lèi)加載機(jī)制的前三篇文章柏肪,詳細(xì)闡述了Class文件的組成部分,每部分的含義芥牌,結(jié)構(gòu)烦味,以及使用方法。因?yàn)樗翘摂M機(jī)執(zhí)行引擎的數(shù)據(jù)入口,也是Java技術(shù)體系最重要的基礎(chǔ)構(gòu)成之一谬俄。

Class文件格式所具備的平臺(tái)中立柏靶、緊湊穩(wěn)定溃论、可擴(kuò)展的特點(diǎn)屎蜓,是Java技術(shù)體系能夠?qū)崿F(xiàn)平臺(tái)無(wú)關(guān)和語(yǔ)言無(wú)關(guān)的重要支柱

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市钥勋,隨后出現(xiàn)的幾起案子炬转,更是在濱河造成了極大的恐慌,老刑警劉巖算灸,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件扼劈,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡菲驴,警方通過(guò)查閱死者的電腦和手機(jī)荐吵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)赊瞬,“玉大人先煎,你說(shuō)我怎么就攤上這事∩” “怎么了榨婆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)褒侧。 經(jīng)常有香客問(wèn)我良风,道長(zhǎng),這世上最難降的妖魔是什么闷供? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任烟央,我火速辦了婚禮,結(jié)果婚禮上歪脏,老公的妹妹穿的比我還像新娘疑俭。我一直安慰自己,他們只是感情好婿失,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布钞艇。 她就那樣靜靜地躺著,像睡著了一般豪硅。 火紅的嫁衣襯著肌膚如雪哩照。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,754評(píng)論 1 307
  • 那天懒浮,我揣著相機(jī)與錄音飘弧,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛次伶,可吹牛的內(nèi)容都是我干的痴昧。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼冠王,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赶撰!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起版确,我...
    開(kāi)封第一講書(shū)人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤扣囊,失蹤者是張志新(化名)和其女友劉穎乎折,沒(méi)想到半個(gè)月后绒疗,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骂澄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年吓蘑,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片坟冲。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡磨镶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出健提,到底是詐尸還是另有隱情琳猫,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布私痹,位于F島的核電站脐嫂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏紊遵。R本人自食惡果不足惜账千,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暗膜。 院中可真熱鬧匀奏,春花似錦丈牢、人聲如沸蛾茉。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)粟按。三九已至懂版,卻和暖如春盖腿,著一層夾襖步出監(jiān)牢的瞬間诫隅,已是汗流浹背钉凌。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工咧最, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓矢沿,卻偏偏與公主長(zhǎng)得像滥搭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子捣鲸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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