Java字節(jié)碼指令解析

字節(jié)碼與數(shù)據(jù)類(lèi)型

在Java虛擬機(jī)的指令集中霎俩,大多數(shù)的指令都包含了其操作所對(duì)應(yīng)的數(shù)據(jù)類(lèi)型信息哀军。

加載和存儲(chǔ)指令

加載和存儲(chǔ)指令用于將數(shù)據(jù)在幀棧中的局部變量表和操作數(shù)棧之間來(lái)回傳輸。這些指令包括如下內(nèi)容:
1:將一個(gè)局部變量加載到操作棧:iload打却、iload_<n>杉适、lload、lload_<n>柳击、fload猿推、fload_<n>、dload捌肴、dload_<n>蹬叭、aload、aload_<n>状知。
2:將一個(gè)數(shù)值從操作數(shù)棧存儲(chǔ)到局部變量表:istore秽五、istore_<n>、lstore试幽、lstore_<n>筝蚕、fstore、fstore_<n>铺坞、dstore起宽、dstore_<n>、astore济榨、astore_<n>坯沪;
3:將一個(gè)常量加載到操作數(shù)棧:bipush、sipush擒滑、ldc腐晾、ldc_w、ldc2_w丐一、aconst_null藻糖、iconst_ml、iconst_<i>库车、lconst_<l>巨柒、fconst_<f>、dconst_<d>柠衍;
4:擴(kuò)充局部變量表的訪問(wèn)索引指令:wide洋满。

存儲(chǔ)數(shù)據(jù)的操作數(shù)棧和局部變量表主要就是由加載和存儲(chǔ)指令進(jìn)行操作,除此之外珍坊,還有少量指令牺勾,如訪問(wèn)對(duì)象的字段或數(shù)組元素的指令也會(huì)向操作數(shù)棧傳輸數(shù)據(jù)。

注意:上面類(lèi)似這樣的格式:iload_<n>:代表了iload_0阵漏、iload_1驻民、iload_2和iload_3這幾條指令

運(yùn)算指令

運(yùn)算或算數(shù)指令用于對(duì)兩個(gè)操作數(shù)棧上的值進(jìn)行某種特定運(yùn)算,并把結(jié)果重新存入到操作棧頂履怯。大體上算數(shù)指令可以分為兩種:對(duì)整型數(shù)據(jù)進(jìn)行運(yùn)算的指令和對(duì)浮點(diǎn)型數(shù)據(jù)進(jìn)行運(yùn)算的指令川无,無(wú)論哪種算數(shù)指令,都使用Java虛擬機(jī)的數(shù)據(jù)類(lèi)型虑乖,由于沒(méi)有直接支持byte懦趋、short、char和boolean類(lèi)型的算術(shù)指令疹味,對(duì)于這類(lèi)數(shù)據(jù)的運(yùn)算仅叫,應(yīng)使用操作int類(lèi)型的指令代替。整數(shù)和浮點(diǎn)數(shù)的算數(shù)指令在溢出和被除零的時(shí)候也有各自不相同的行為表現(xiàn)糙捺。所有的算術(shù)指令如下:

  • 加法指令: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疏之、lshl殿雪、fshl、dshl锋爪;
  • 按位或指令:ior丙曙、lor;
  • 按位與指令:iand其骄、land亏镰;
  • 按位異或指令:ixor、lxor拯爽;
  • 局部變量自增指令:iinc索抓;
  • 比較指令:dcmpg、dcmpl毯炮、fcmpg逼肯、fcmpl、lcmp桃煎。
類(lèi)型轉(zhuǎn)換指令

類(lèi)型轉(zhuǎn)換指令可以將兩種不同的數(shù)值類(lèi)型的進(jìn)行相互轉(zhuǎn)換篮幢,這些轉(zhuǎn)換操作一般用于實(shí)現(xiàn)用戶代碼中的顯示類(lèi)型轉(zhuǎn)換操作或者用來(lái)處理字節(jié)碼指令集中數(shù)據(jù)類(lèi)型相關(guān)指令無(wú)法與數(shù)據(jù)類(lèi)型一一對(duì)應(yīng)的問(wèn)題。

JVM直接支持(即轉(zhuǎn)換時(shí)無(wú)需顯示的轉(zhuǎn)換指令)以下數(shù)值類(lèi)型的寬化類(lèi)型轉(zhuǎn)換(Widening Numberic Conversions为迈,即小范圍類(lèi)型向大范圍類(lèi)型的安全轉(zhuǎn)換):
int類(lèi)型到long三椿、float缺菌、或者double類(lèi)型;
long類(lèi)型到float搜锰、double類(lèi)型伴郁;
float類(lèi)型到double類(lèi)型。
相對(duì)的纽乱,處理窄化類(lèi)型轉(zhuǎn)換(Narrowing Numberic Conversions)時(shí) 蛾绎,必須顯示地使用轉(zhuǎn)換指令來(lái)完成昆箕,這些轉(zhuǎn)換指令包括:i2b鸦列、i2c、i2s鹏倘、l2i薯嗤、f2i、f2l纤泵、d2i骆姐、d2l、d2f捏题。窄化類(lèi)型轉(zhuǎn)換可能導(dǎo)致轉(zhuǎn)換結(jié)果產(chǎn)生不同的正負(fù)號(hào)玻褪、不同的數(shù)量級(jí)情況、轉(zhuǎn)換過(guò)程很可能導(dǎo)致數(shù)值的精確度丟失公荧。
注意:數(shù)值類(lèi)型的窄化處理永遠(yuǎn)不可能導(dǎo)致虛擬機(jī)拋出運(yùn)行時(shí)異常带射。

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

雖然類(lèi)實(shí)例和數(shù)組都是對(duì)象,但JVM對(duì)類(lèi)實(shí)例和數(shù)組的創(chuàng)建與操作采用了不同的字節(jié)碼指令循狰。對(duì)象創(chuàng)建后窟社,就可以通過(guò)對(duì)象訪問(wèn)指令獲取對(duì)象實(shí)例或者數(shù)組中的字段或者數(shù)組元素,這些指令如下:
1绪钥,創(chuàng)建類(lèi)實(shí)例的指令:new灿里;
2,創(chuàng)建數(shù)組的指令:newarray程腹、anewarray匣吊、multianewarray;
3寸潦,訪問(wèn)類(lèi)字段(static字段荐绝,或者成為類(lèi)變量)和實(shí)例字段(非static字段,或者稱(chēng)為實(shí)例變量)的指令:getfield倔既、putfield善已、getstatic、putstatic池户;
4咏雌,把一個(gè)數(shù)組元素加載到操作數(shù)棧的指令:baload凡怎、caload、saload赊抖、iaload统倒、laload、faload氛雪、daload房匆、aaload;
5报亩,將一個(gè)操作數(shù)棧的值存儲(chǔ)到數(shù)組元素中的指令:bastore浴鸿、castore、sastore弦追、iastore岳链、fastore、dastore劲件、aastore掸哑;
6,取數(shù)組長(zhǎng)度的指令:arraylength零远;
7苗分,檢查類(lèi)實(shí)例類(lèi)型的指令:instanceof、checkcast牵辣。

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

如同操作一個(gè)普通數(shù)據(jù)結(jié)構(gòu)中的堆棧那樣摔癣,JVM直接提供了一些用于直接操作操作數(shù)棧的指令,包括:
1服猪,將操作數(shù)棧的棧頂一個(gè)或兩個(gè)元素出棧:pop供填、pop2;
2罢猪,復(fù)制棧頂一個(gè)或兩個(gè)數(shù)值并將復(fù)制值或雙份的復(fù)制值重新壓入棧頂:dup近她、dup2、dup_x1膳帕、dup2_x1粘捎、dup_x2、dup2_x2危彩;
3攒磨,將棧最頂端的兩個(gè)數(shù)值互換:swap。

控制轉(zhuǎn)移指令

控制轉(zhuǎn)移指令可以讓JVM有條件或者無(wú)條件地從指定的位置指令而不是控制轉(zhuǎn)移指令的下一條指令繼續(xù)執(zhí)行程序汤徽,從概念模型上理解娩缰,可以認(rèn)為控制轉(zhuǎn)移指令就是在有條件或者無(wú)條件地修改PC寄存器的值≮烁控制轉(zhuǎn)移指令如下:
條件分支:ifeq拼坎、iflt浮毯、ifle、ifne泰鸡、ifgt债蓝、ifge、ifnull盛龄、ifnonnull饰迹、if_icmpeq、if_icmpne余舶、if_icmplt啊鸭、if_icmpgt、if_icmple欧芽、if_icmpge莉掂、if_acmpeq和if_acmpne葛圃;
復(fù)合條件分支:tableswitch千扔、lookupswitch;
無(wú)條件分支:goto库正、goto_w曲楚、jsr、jsr_w褥符、ret龙誊;

在JVM中有專(zhuān)門(mén)的指令集用來(lái)處理int(boolean型、byte型喷楣、char型和short型的條件分支比較也都用int型趟大,對(duì)于float型、double型的條件分支比較操作則會(huì)先執(zhí)行相應(yīng)類(lèi)型的比較運(yùn)算指令铣焊,它會(huì)返回一個(gè)整型值到操作數(shù)棧中逊朽,然后按int型執(zhí)行)和reference類(lèi)型的條件分支比較操作,為了可以無(wú)需明顯標(biāo)識(shí)一個(gè)實(shí)體值是否為null曲伊,也有專(zhuān)門(mén)的指令來(lái)檢測(cè)null值叽讳。

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

方法調(diào)用指令舉例:
invokevirtual指令用于調(diào)用對(duì)象的實(shí)例方法,根據(jù)對(duì)象的實(shí)際類(lèi)型進(jìn)行分派(虛方法分派)坟募,這也是java語(yǔ)言最常見(jià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í)行該方法,前面4條調(diào)用指令的分派邏輯都固話在JVM內(nèi)部犁苏,而invokedynamic指令的分派邏輯是由用戶所設(shè)定的引導(dǎo)方法決定的硬萍。
方法調(diào)用指令與數(shù)據(jù)類(lèi)型無(wú)關(guān),而方法返回指令是根據(jù)返回值的類(lèi)型區(qū)分的围详,包括ireturn(當(dāng)返回值是boolean朴乖、byte、char助赞、short和int類(lèi)型使用)买羞、lreturn、freturn雹食、dreturn和areturn畜普,另外還有一條return指令供聲明為void的方法、實(shí)例初始化方法以及類(lèi)和接口的類(lèi)初始化方法使用群叶。

異常處理指令

在Java程序中顯示拋出異常的操作(throw語(yǔ)句)都有athrow指令來(lái)實(shí)現(xiàn)吃挑,除了用throw語(yǔ)句顯示拋出異常的情況之外,JVM規(guī)范還規(guī)定了許多運(yùn)行時(shí)異常會(huì)在其他Java虛擬機(jī)指令檢測(cè)到異常時(shí)自動(dòng)拋出街立。而在Java虛擬機(jī)之中舶衬,處理異常不是由字節(jié)碼指令來(lái)實(shí)現(xiàn)的,而是采用異常表來(lái)完成的赎离。

同步指令

JVM可以支持方法級(jí)的同步和方法內(nèi)部一段指令序列的同步逛犹,這兩種同步都使用管程(Monitor)來(lái)支持的。
五:公有設(shè)計(jì)和私有實(shí)現(xiàn)

JVM規(guī)范描繪了JVM應(yīng)有的共同程序存儲(chǔ)格式:Class文件格式以及字節(jié)碼指令集梁剔。
理解公有設(shè)計(jì)和私有實(shí)現(xiàn)之間的分界線是很有必要的虽画,JVM實(shí)現(xiàn)必須能夠讀取Class文件并精確實(shí)現(xiàn)包含在其中的JVM代碼的語(yǔ)義。按照虛擬機(jī)規(guī)范一成不變地逐字實(shí)現(xiàn)其中的要求內(nèi)容是一種途徑荣病;但是也可以在滿足JVM規(guī)范要求的情況下對(duì)具體實(shí)現(xiàn)做出修改和優(yōu)化也是可以的码撰,并且JVM規(guī)范明確鼓勵(lì)這么做。
虛擬機(jī)實(shí)現(xiàn)者可以使用這種伸縮性來(lái)讓虛擬機(jī)實(shí)現(xiàn)更高的性能众雷、更低的內(nèi)存消耗或者更好的可移植性灸拍,選擇哪種特性取決于JVM實(shí)現(xiàn)的目標(biāo)和關(guān)注點(diǎn)。虛擬機(jī)實(shí)現(xiàn)主要有以下兩種方式:

  • 將輸入的虛擬機(jī)代碼在加載或執(zhí)行時(shí)翻譯成另外一種虛擬機(jī)的指令集砾省;
  • 將輸入的虛擬機(jī)代碼在加載或執(zhí)行時(shí)翻譯成宿主機(jī)CPU的本地指令集鸡岗。

精確定義的虛擬機(jī)和目標(biāo)文件格式不應(yīng)當(dāng)對(duì)虛擬機(jī)實(shí)現(xiàn)者創(chuàng)造性產(chǎn)生太多的限制,Java虛擬機(jī)應(yīng)被設(shè)計(jì)成可以允許有眾多不同的實(shí)現(xiàn)编兄,并且各種實(shí)現(xiàn)可以在保持兼容性的同時(shí)提供不同的轩性、新的、有趣的解決方案狠鸳。

六:Class文件結(jié)構(gòu)的發(fā)展
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揣苏,一起剝皮案震驚了整個(gè)濱河市悯嗓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌卸察,老刑警劉巖脯厨,帶你破解...
    沈念sama閱讀 222,252評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坑质,居然都是意外死亡合武,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)涡扼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)稼跳,“玉大人,你說(shuō)我怎么就攤上這事吃沪√郎疲” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,814評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵票彪,是天一觀的道長(zhǎng)红淡。 經(jīng)常有香客問(wèn)我,道長(zhǎng)抹镊,這世上最難降的妖魔是什么锉屈? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,869評(píng)論 1 299
  • 正文 為了忘掉前任荤傲,我火速辦了婚禮垮耳,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘遂黍。我一直安慰自己终佛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布雾家。 她就那樣靜靜地躺著铃彰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芯咧。 梳的紋絲不亂的頭發(fā)上牙捉,一...
    開(kāi)封第一講書(shū)人閱讀 52,475評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音敬飒,去河邊找鬼邪铲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛无拗,可吹牛的內(nèi)容都是我干的带到。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼英染,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼揽惹!你這毒婦竟也來(lái)了被饿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,924評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤搪搏,失蹤者是張志新(化名)和其女友劉穎狭握,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體疯溺,經(jīng)...
    沈念sama閱讀 46,469評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哥牍,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了喝检。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗅辣。...
    茶點(diǎn)故事閱讀 40,680評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖挠说,靈堂內(nèi)的尸體忽然破棺而出澡谭,到底是詐尸還是另有隱情,我是刑警寧澤损俭,帶...
    沈念sama閱讀 36,362評(píng)論 5 351
  • 正文 年R本政府宣布蛙奖,位于F島的核電站,受9級(jí)特大地震影響杆兵,放射性物質(zhì)發(fā)生泄漏雁仲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評(píng)論 3 335
  • 文/蒙蒙 一琐脏、第九天 我趴在偏房一處隱蔽的房頂上張望攒砖。 院中可真熱鬧,春花似錦日裙、人聲如沸吹艇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,519評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)受神。三九已至,卻和暖如春格侯,著一層夾襖步出監(jiān)牢的瞬間鼻听,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,621評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工联四, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撑碴,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,099評(píng)論 3 378
  • 正文 我出身青樓碎连,卻偏偏與公主長(zhǎng)得像灰羽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評(píng)論 2 361