一步一步實現(xiàn)簡單安卓性能監(jiān)控SDK之熟悉字節(jié)碼指令

  1. 字節(jié)碼與數(shù)據(jù)類型

在Java虛擬機的指令集中,大多數(shù)的指令都包含了操作所對應的數(shù)據(jù)類型信息蓉坎。比如iload指令表示從局部變量表中加載int型數(shù)據(jù)到操作數(shù)棧中澳眷,而fload表示加載float類型的數(shù)據(jù)。不過袍嬉,這兩條指令再虛擬機的內(nèi)部可能是由同一段代碼來實現(xiàn)的境蔼,但在class文件中必須有自己的操作碼灶平。

我們已經(jīng)知道Java指令的長度只有一個字節(jié)伺通,這就限制了指令集的大小。如果每個指令都像上面兩個指令那樣包含所有的數(shù)據(jù)類型逢享,那么就有可能導致指令過多罐监。因此,Java虛擬機的指令集對于特定的操作只提供了有限的類型相關指令去支持它瞒爬。比如弓柱,大多數(shù)指令沒有支持整數(shù)類型byte、char和short侧但,甚至沒有指令支持boolean類型矢空。

這些指令中都有特殊的字符來表示專門支持的類型:i代表int類型,l代表long禀横,s代表short屁药,b代表byte,c代表char柏锄,f代表float酿箭,d代表double缭嫡,a代表Reference妇蛀。

這里僅僅介紹一下指令的種類以及作用,并不會過多的介紹各個指令的含義以及使用有勾,需要的話可以查看《Java虛擬機規(guī)范(Java SE 7版)》蔼卡。

  1. 加載和存儲指令

加載指令用于將局部變量表中的數(shù)據(jù)傳送到操作數(shù)棧中雇逞,而存儲指令用于將操作數(shù)棧中的結果傳送到局部變量表中茁裙。這類指令包括如下幾種:

將一個局部變量加載到操作棧晤锥,比如iload矾瘾、iload、fload蛉迹、fload放妈、lload、lload珍策、dload宅倒、dload唉堪、aload、aload链方;

將一個數(shù)值從操作數(shù)棧存儲到局部變量表祟蚀,比如istore前酿、istore罢维、lstore肺孵、lstore、fstore吓肋、fstore瑰艘、dstore紫新、dstore弊琴、astore敲董、astore;

將一個常量加載到操作數(shù)棧腋寨,比如bipush、sipush化焕、ldc、ldc_w撒桨、ldc2w查刻、aconst_null凤类、iconst_ml穗泵、iconst、lconst_谜疤、fconst_现诀、dconst_仔沿;

擴充局部變量表的訪問索引的指令:wide;

上面中帶尖括號的指令實際是一組指令。比如iload烘浦,代表了iload_1、iload_2和iload_3闷叉。這幾組指令是某個帶操作數(shù)的指令(比如iload)的特殊形式握侧,它們省略了操作數(shù),不過操作數(shù)隱含在指令中嘿期。

  1. 運算指令

運算或算術指令用于對一個或兩個操作數(shù)棧上的值進行某種特定的運算品擎,并將結果存入棧頂。大體上可以分為兩種备徐,對整數(shù)進行運算的指令和對浮點數(shù)進行運算的指令萄传。不過,由于沒有支持byte蜜猾、short秀菱、char和boolean的算術指令,對于這些數(shù)據(jù)的運算蹭睡,會把它們轉化為int類型進行運算衍菱。指令列出如下:
<pre>
加法指令: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霞扬;
</pre>

  1. 類型轉換指令

類型轉換指令用來將兩種不同類型進行轉換,這些轉換操作一般用于實現(xiàn)代碼中的顯示類型轉換操作枫振,或者前面提到的字節(jié)碼指令集中數(shù)據(jù)類型相關指令無法與數(shù)據(jù)類型一一對應的問題喻圃。

虛擬機直接支持寬化類型轉換,即小范圍類型向大范圍類型的安全轉換粪滤,不需要顯示的轉換指令斧拍。

但是處理窄化類型轉換時,必須顯示使用轉換指令來完成杖小,這些指令包括:i2b肆汹、i2c愚墓、i2s、l2i昂勉、f2l浪册、d2i、d2l和d2f岗照。這些指令可能會導致數(shù)值的精度丟失村象。

  1. 對象創(chuàng)建與訪問指令

雖然類實例和數(shù)組都是對象,但是虛擬機創(chuàng)建類對象和數(shù)組的指令是不同的攒至。對象創(chuàng)建后厚者,就可以通過對象訪問指令獲取對象實例或者數(shù)組實例中的字段或數(shù)組元素,指令如下:

創(chuàng)建類實例的指令:new迫吐;

創(chuàng)建數(shù)組的指令:newarray库菲、anewarray、multianewarray志膀;

訪問類字段和實例字段的指令:getfield蝙昙、putfield、getstatic梧却、putstatic奇颠;

把一個數(shù)組元素加載到操作數(shù)棧的指令:baload、caload放航、saload烈拒、iaload、laload广鳍、faload荆几、daload、aaload赊时;

將一個操作數(shù)棧的值存儲到數(shù)組元素中的指令:bastore吨铸、castore、sastore祖秒、iastore诞吱、fastore、dastore竭缝、aastore房维;

取數(shù)組長度的指令:arraylength;

檢查類實例類型的指令:instanceof抬纸、checkcast咙俩;

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

就像操作一個普通的棧一樣耘擂,Java虛擬機提供了一些用于直接操作操作數(shù)棧的指令镇匀,包括:

將操作數(shù)棧的棧頂一個或兩個元素出棧:pop、pop2;

復制棧頂一個或兩個數(shù)值并將復制值或雙份的復制值重新壓入棧頂:dup颠悬、dup2谐宙、dup_x1拇派、dup2_x1后室、dup_x2、dup2_x2独撇;

將棧頂最頂端的兩個數(shù)值互換:swap屑墨;

  1. 控制轉移指令

控制轉移指令可以讓Java虛擬機有條件或無條件的從指定的位置指令而不是控制轉移指令的下一條指令繼續(xù)執(zhí)行,可以理解為控制轉移指令改變了PC寄存器的值纷铣。指令如下:

條件分支:ifeq卵史、iflt、ifle搜立、ifgt以躯、ifge、ifnonnull啄踊、if_icmpeq忧设、if_icmpne、if_icmplt颠通、if_icmpgt址晕、、if_icmpge顿锰、if_acmpeq和if_acmpne谨垃;

復合條件分支:tableswitch、lookupswitch硼控;

無條件分支:goto刘陶、goto_w、jsr牢撼、jsr_w匙隔、ret;

  1. 方法調用和返回指令

這里僅僅列出5條用于方法調用的指令:

invokevirtual指令用于調用對象的實例方法熏版,根據(jù)對象的實際類型進行分派(虛方法分派)纷责,這也是Java語言中最常見的方法分派方式;

invokeinterface指令用于調用接口方法纳决,它會在運行時搜索一個實現(xiàn)了這個接口方法的對象碰逸,找出適合的方法進行調用;

invokespecial指令用于調用一些需要特殊處理的實例方法阔加,包括實例初始化方法、私有方法和父類方法满钟;

invokestatic指令用于調用類方法(static方法)胜榔;

invokedynamic指令用于在運行時動態(tài)解析出調用點限定符索引用的方法胳喷,并執(zhí)行方法,前面4條指令的分派邏輯都固化在Java虛擬機內(nèi)部夭织,而invokedynamic指令的分派邏輯是由用戶所設定的引導方法決定的吭露;

方法調用指令與類型無關,但是方法返回指令是根據(jù)返回值的類型區(qū)分的尊惰,包括ireturn讲竿、lreturn、freturn弄屡、dreturn和areturn题禀,另外還有一個return指令供聲明為void的方法、實例初始化方法以及類和接口的類初始化方法使用膀捷。

  1. 異常處理指令

在Java程序中顯式拋出異常的操作(throw語句)都是由athrow指令來實現(xiàn)的迈嘹,除了用throw語句顯式拋出異常外,Java虛擬機規(guī)范還規(guī)定了許多運行時異常會在其他Java虛擬機指令檢測到異常狀況時自動拋出全庸。

而在Java虛擬機中秀仲,處理異常(catch語句)不是由字節(jié)碼指令來完成的,而是采用異常表來完成的壶笼。

  1. 同步指令

Java虛擬機可以支持方法級的同步和方法內(nèi)部一段指令序列的同步神僵,這兩種同步結構都是使用管程(Monitor)來支持的。

方法級的同步是隱式的覆劈,即不需要通過字節(jié)碼指令來控制挑豌,它實現(xiàn)在方法調用和返回操作中。虛擬機可以從方法常量池的方法表結構中的ACC_SYNCHRONIZED訪問標志得知一個方法是否聲明為同步方法墩崩。當方法調用時氓英,調用指令就會去檢查方法的ACC_SYNCHRONIZED訪問標志是否被設置了,如果設置鹦筹,執(zhí)行線程就要求持有管程铝阐。在方法執(zhí)行期間,執(zhí)行線程持有了管程铐拐,其他任何線程都無法再獲取到同一個管程徘键。如果一個方法在執(zhí)行期間發(fā)生了異常,并在方法中無法處理此異常遍蟋,那么這個同步方法所持有的管程將在異常拋出后自動釋放吹害。

同步一段指令集序列通常是由Java語言中的synchronized語句塊表示的,Java虛擬機的指令集中有monitorenter和monitorexit指令來支持synchronized關鍵字的語義虚青。正確實現(xiàn)synchronized關鍵字需要Javac編譯器和Java虛擬機兩者共同協(xié)作它呀。編譯器必須保證每個monitorenter指令都有對應的monitorexit指令。

參考:http://cyw3.github.io/YalesonChan/2016/Java-Byte-Code.html#4.1

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市纵穿,隨后出現(xiàn)的幾起案子下隧,更是在濱河造成了極大的恐慌,老刑警劉巖谓媒,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淆院,死亡現(xiàn)場離奇詭異,居然都是意外死亡句惯,警方通過查閱死者的電腦和手機土辩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來抢野,“玉大人拷淘,你說我怎么就攤上這事∶杀#” “怎么了辕棚?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長邓厕。 經(jīng)常有香客問我逝嚎,道長,這世上最難降的妖魔是什么详恼? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任补君,我火速辦了婚禮,結果婚禮上昧互,老公的妹妹穿的比我還像新娘挽铁。我一直安慰自己,他們只是感情好敞掘,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布叽掘。 她就那樣靜靜地躺著,像睡著了一般玖雁。 火紅的嫁衣襯著肌膚如雪更扁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天赫冬,我揣著相機與錄音浓镜,去河邊找鬼。 笑死劲厌,一個胖子當著我的面吹牛膛薛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播补鼻,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼哄啄,長吁一口氣:“原來是場噩夢啊……” “哼雅任!你這毒婦竟也來了?” 一聲冷哼從身側響起增淹,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤椿访,失蹤者是張志新(化名)和其女友劉穎乌企,沒想到半個月后虑润,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡加酵,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年拳喻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猪腕。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡冗澈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出陋葡,到底是詐尸還是另有隱情亚亲,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布腐缤,位于F島的核電站捌归,受9級特大地震影響,放射性物質發(fā)生泄漏岭粤。R本人自食惡果不足惜惜索,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望剃浇。 院中可真熱鬧巾兆,春花似錦、人聲如沸虎囚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淘讥。三九已至圃伶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間适揉,已是汗流浹背留攒。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嫉嘀,地道東北人炼邀。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像剪侮,于是被迫代替她去往敵國和親拭宁。 傳聞我的和親對象是個殘疾皇子洛退,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

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