1. 程式人生 > >位元組碼指令簡介

位元組碼指令簡介

摘自《深入理解 Java 虛擬機器:JVM 高階特性與最佳實踐》(第二版)

        Java 虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的數字(稱為操作碼,Opcode)以及跟隨其後的零至多個代表此操作所需引數(稱為運算元,Operands)而構成。由於 Java 虛擬機器採用面向運算元棧而不是暫存器的架構,所以大多數的指令都不包含運算元,只有一個操作碼。

        位元組碼指令集是一種具有鮮明特點、優劣勢都很突出的指令集架構,由於限制了 Java 虛擬機器操作碼的長度為一個位元組(即 0 ~ 255),這意味著指令集的操作碼總數不可能超過 256 條;又由於 Class 檔案格式放棄了編譯後代碼的運算元長度對齊,這就意味著虛擬機器處理那些超過一個位元組資料的時候,不得不在執行時位元組

中重建出具體資料的結構,如果要將一個 16 位長度的無符號整數使用兩個無符號位元組儲存起來(將它們命名為 byte1 和 byte2),那它們的值應該是這樣的:

(byte1 << 8) | byte2

        這種操作在某種程度上會導致解釋執行位元組碼時損失一些效能。但這樣做的優勢也非常明顯,放棄了運算元長度對齊(注:位元組碼指令流基本上都是單位元組對齊的,只有 “tableswitch” 和 “lookupswitch” 兩條指令例外,由於它們的運算元比較特殊,是以 4 位元組為界劃分開的,所以這兩條指令也需要預留出相應的空位進行填充來實現對齊),就意味著可以省略很多填充和間隔符號;用一個位元組來代表操作碼,也是為了儘可能獲得短小精幹的編譯程式碼。這種追求儘可能小資料量、高傳輸效率的設計是由 Java 語言設計之初面向網路、智慧家電的技術背景所決定的,並一直沿用至今。

        如果不考慮異常處理的話,那麼 Java 虛擬機器的直譯器可以使用下面這個虛擬碼當做最基本的執行模型來理解,這個執行模型雖然很簡單,但依然可以有效地工作:

do {
     自動計算 PC 暫存器的值加 1;
     根據 PC 暫存器的指示位置,從位元組碼流中取出操作碼;
     if ( 位元組碼存在運算元 ) 從位元組碼流中取出運算元;
     執行操作碼所定義的操作;
} while ( 位元組碼流長度 > 0 )

位元組碼與資料型別

        在 Java 虛擬機器的指令集中,大多數的指令都包含了其操作所對應的資料型別資訊。例如,iload 指令用於從區域性變量表中載入 int 型的資料到運算元棧中,而 fload 指令載入的則是 float 型別的資料。這兩條指令的操作在虛擬機器內部可能會是由同一段程式碼來實現的,但在 Class 檔案中它們必須擁有各自獨立的操作碼。

        對於大部分與資料型別相關的位元組碼指令,它們的操作碼助記符中都有特殊的字元來表明專門為哪種資料型別服務:i 代表對 int 型別的資料操作,l 代表 long,s 代表 short,b 代表 byte,c 代表 char,f 代表 float,d 代表 double,a 代表 reference。也有一些指令的助記符中沒有明確地指明操作型別的字母,如 arraylength 指令,它沒有代表資料型別的特殊字元,但運算元永遠只能是一個數組型別的物件。還有另外一些指令,如無條件跳轉指令 goto 則是與資料型別無關的。

        由於 Java 虛擬機器的操作碼長度只有一個位元組,所以包含了資料型別的操作碼就為指令集的設計帶來了很大的壓力:如果每一種與資料型別相關的指令都支援 Java 虛擬機器所有執行時資料型別的話,那指令的數量恐怕就會超出一個位元組所能表示的數量範圍了。因此,Java 虛擬機器的指令集對於特定的操作只提供了有限的型別相關指令去支援它,換句話說,指令集將會故意被設計成非完全獨立的(Java 虛擬機器規範中把這種特性稱為 “Not Orthogonal”,即並非每種資料型別和每一種操作都有對應的指令)。有一些單獨的指令可以在必要的時候用來將一些不支援的型別轉換為可被支援的型別。

        表 6-31 列舉了 Java 虛擬機器所支援的與資料型別相關的位元組碼指令,通過使用資料型別列所代表的特殊字元替換 opcode 列的指令模板中的 T,就可以得到一個具體的位元組碼指令。如果在表中指令模板與資料型別兩列共同確定的格為空,則說明虛擬機器不支援這種資料型別執行這項操作。例如,load 指令又操作 int 型別的 iload,但是沒有操作 byte 型別的同類指令。

        注意,從表 6-31 可以看出,大部分的指令都沒有支援整數型別 byte、char 和 short,甚至沒有任何指令支援 boolean 型別。編譯器會在編譯器或執行期將byte 和 short 型別的資料帶符號擴充套件(Sign-Extend)為相應的 int 型別資料,將boolean 和 char 型別資料零位擴充套件(Zero-Extend)為相應的 int 型別資料。與之類似,在處理 boolean、byte、short 和 char 型別的陣列時,也會轉換為使用對應的 int 型別的位元組碼指令來處理。因此,大多數對於 boolean、byte、short 和 char 型別資料的操作,實際上都是使用相應的 int 型別作為運算型別(Computational Type)。

表 6-31  Java 虛擬機器指令集所支援的資料型別

        在本章中,受篇幅所限,無法對位元組碼指令集中每條指令進行逐一講解,但閱讀位元組碼作為了解 Java 虛擬機器的基礎技能,是一項應當熟練掌握的能力。筆者將位元組碼操作按用途大致分為 9 類,按照分類來概略介紹一下這些指令的用法。如果需要了解更詳細的資訊,可以參考閱讀《Java 虛擬機器規範(Java SE 7 版)》的第 6 章。

載入和儲存指令

        載入和儲存指令用於將資料在棧幀中的區域性變量表和運算元棧之間來回傳輸,這類指令包括如下內容。

  • 將一個區域性變數載入到操作棧:iload、iload_<n>、lload、lload_<n>、fload、fload_<n>、dload、dload_<n>、aload、aload_<n>。
  • 將一個數值從運算元棧儲存到區域性變量表:istore、istore_<n>、lstore、lstore_<n>、fstore、fstore_<n>、dstore、dstore_<n>、astore、astore_<n>。
  • 將一個常量載入到運算元棧:bipush、sipush、ldc、ldc_w、ldc2_w、aconst_null、iconst_m1、iconst_<i>、lconst_<l>、fconst_<f>、dconst_<d>。
  • 擴充區域性變數的訪問索引的指令:wide。

        儲存資料的運算元棧和區域性變量表主要就是由載入儲存指令進行操作,除此之外,還有少量指令,如訪問物件的欄位陣列元素的指令也會向運算元棧傳輸資料。

        上面所列舉的指令助記符中,有一部分是以尖括號結尾的(例如 iload_<n>),這些指令助記符實際上是代表了一組指令(例如 iload_<n>,它代表了 iload_0、iload_1、iload_2 和 iload_3 這幾條指令)。這幾組指令都是某個帶有一個運算元的通用指令(例如 iload)的特殊形式,對於這若干組特殊指令來說,它們省略掉了顯示的運算元,不需要進行取運算元的動作,實際上運算元就隱含在指令中。除了這點之外,它們的語義與原生的通用指令完全一致(例如 iload_0 的語義與運算元為 0 時的 iload 指令語義完全一致)。這種指令表示方法在這裡以及《Java 虛擬機器規範》中都是通用的。

運算指令

        運算或算術指令用於對兩個運算元棧上的值進行某種特定運算,並把結果重新存入到操作棧頂。大體上算術指令可以分為兩種:對整型資料進行運算的指令與對浮點型資料進行運算的指令,無論是哪種算術指令,都使用 Java 虛擬機器的資料型別,由於沒有直接支援 byte、short、char 和 boolean 型別的算術指令,對於這類資料的運算,應使用操作 int 型別的指令代替。整數與浮點數的算術指令在溢位和被零除的時候也有各自不同的行為表現,所有的算術指令如下。

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

        Java 虛擬機器的指令集直接支援了在 《Java 語言規範》中描述的各種對整數及浮點數操作(參見《Java 語言規範(第 3 版)》中的 4.2.2 節和 4.2.4 節)的語義。資料運算可能會導致溢位。例如兩個很大的正整數相加,結果可能會是一個負數,這種數學上不可能出現的溢位現象,對於程式設計師來說是很容易理解的,但其實 Java 虛擬機器規範沒有明確定義過整型資料溢位的具體運算結果,僅規定了在處理整型資料時,只有除法指令(idiv 和 ldiv)以及求餘指令(irem 和 lrem)中當出現除數為零時會導致虛擬機器丟擲 ArithmeticException 異常其餘任何整型數運算場景都不應該丟擲執行時異常

        Java 虛擬機器規範要求虛擬機器實現在處理浮點數時,必須嚴格遵循 IEEE 754 規範中所規定的行為和限制。也就是說,Java 虛擬機器必須完全支援 IEEE 754 中定義的非正規浮點數值(Denormalized Floating-Point Numbers)和逐級下溢(Gradual Underflow)的運算規則。這些特徵將會使某些數值演算法處理起來變得相對容易一些。

        Java 虛擬機器要求在進行浮點數運算時,所有的運算結果都必須舍入到適當的精度,非精確的結果必須舍入為可被表示的最接近的精確值,如果有兩種可表示的形式與該值一樣接近,將優先選擇最低有效位為零的。這種舍入模式也是 IEEE 754 規範中的預設舍入模式,稱為向最接近數舍入模式。

        在把浮點數轉換為整數時,Java 虛擬機器使用 IEEE 754 標準中的向零舍入模式,這種模式的舍入結果會導致數字被截斷,所有小數部分的有效位元組都會被丟棄掉。向零舍入模式將在目標數值型別中選擇一個最接近但是不大於原值的數字來作為最精確的舍入結果。

        另外,Java 虛擬機器在處理浮點數運算時,不會丟擲任何執行時異常(這裡所講的是 Java 語言中的異常,請勿與 IEEE 754 規範中的浮點異常互相混淆,IEEE 754 的浮點異常是一種運算訊號),當一個操作產生溢位時,將會使用有符號的無窮大來表示,如果某個操作結果沒有明確的數學定義的話,將會使用 NaN 值來表示。所有使用 NaN 值作為運算元的算術操作,結果都會返回 NaN。

        在對 long 型別數值進行比較時,虛擬機器採用帶符號的比較方式,而對浮點數值進行比較時(dcmpg、dcmpl、fcmpg、fcmpl),虛擬機器會採用 IEEE 754 規範所定義的無訊號比較(Nonsignaling Comparisons)方式

型別轉換指令

        型別轉換指令可以將兩種不同的數值型別進行相互轉換,這些轉換操作一般用於實現使用者程式碼中的顯示型別轉換操作,或者用來處理本節開篇所提到的位元組碼指令集中資料型別相關指令無法與資料型別一一對應的問題。

        Java 虛擬機器直接支援(即轉換時無需顯示的轉換指令)以下數值型別的寬化型別轉換(Widening Numeric Conversions,即小範圍型別向大範圍型別的安全轉換):

  • int 型別到 long、float 或者 double 型別。
  • long 型別到 float、double 型別。
  • float 型別到 double 型別。

        相對的,處理窄化型別轉換(Narrowing Numeric Conversions)時,必須顯式地使用轉換指令來完成,這些轉換指令包括:i2b、i2c、i2s、l2i、f2i、f2l、d2i、d2l 和 d2f。窄化型別轉換可能會導致轉換結果產生不同的正負號、不同的數量級的情況,轉換過程很可能會導致數值的精度丟失。

        在將 int 或 long 型別窄化轉換為整數型別 T 的時候,轉換過程僅僅是簡單地丟棄除最低位 N 個位元組意外的內容,N 是型別 T 的資料型別長度,這將可能導致轉換結果與輸入值有不同的正負號。這點很容易理解,因為原來符號位處於數值的最高位,高位被丟棄之後,轉換結果的符號就取決於低 N 個位元組的首位了。

        在將一個浮點值窄化轉換為整數型別 T(T 限於 int 或 long 型別之一)的時候,將遵循以下轉換規則:

  • 如果浮點值是 NaN,那轉換結果就是 int 或 long 型別的 0。
  • 如果浮點值不是無窮大的話,浮點值使用 IEEE 754 的向零舍入模式取整,獲得整數值 v,如果 v 在目標型別 T(int 或 long)的表示範圍之內,那轉換結果就是 v。
  • 否則,將根據 v 的符號,轉換為 T 所能表示的最大或者最小整數。

        從 double 型別到 float 型別的窄化轉換過程與 IEEE 754 中定義的一致,通過 IEEE 754 向最接近數舍入模式舍入得到一個可以使用 float 型別表示的數字。如果轉換結果的絕對值太小而無法使用 float 來表示的話,將返回 float 型別的正負零。如果轉換結果的絕對值太大而無法使用 float 來表示的話,將返回 float 型別的正負無窮大,對於 double 型別的 NaN 值將按規定轉換為 float 型別的 NaN 值。

        儘管資料型別窄化轉換可能會發生上限溢位、下限溢位和精度丟失等情況,但是 Java 虛擬機器規範中明確規定數值型別的窄化轉換指令永遠不可能導致虛擬機器丟擲執行時異常。

物件建立與訪問指令

        雖然類例項和陣列都是物件,但 Java 虛擬機器對類例項和陣列的建立與操作使用了不同的位元組碼指令(陣列和普通型別建立過程是不同的)。物件建立後,就可以通過物件訪問指令獲取物件例項或者陣列例項中的欄位或者陣列元素,這些指令如下。

  • 建立類例項的指令:new。
  • 建立陣列的指令:newarray、anewarray、multianewarray。
  • 訪問類欄位(static 欄位,或者成為類變數)和例項欄位(非 static 欄位,或者成為例項變數)的指令:getfield、putfield、getstatic、putstatic。
  • 把一個數組元素載入到運算元棧的指令:baload、caload、saload、iaload、laload、faload、daload、aaload。
  • 將一個運算元棧的值儲存到陣列元素中的指令:bastore、castore、sastore、iastore、fastore、dastore、aastore。
  • 取陣列長度的指令:arraylength。
  • 檢查類例項型別的指令:instanceof、checkcast。

運算元棧管理指令

        如同操作一個普通資料結構中的堆疊那樣,Java 虛擬機器提供了一些用於直接操作運算元棧的指令,包括:

  • 將運算元棧的棧頂一個或兩個元素出棧:pop、pop2。
  • 複製棧頂一個或兩個數值並將複製值或雙份的複製重新壓入棧頂:dup、dup2、dup_x1、dup2_x1、dup_x2、dup2_x2。
  • 將棧最頂端的兩個數值互換:swap。

控制轉移指令

        控制轉移指令可以讓 Java 虛擬機器有條件或無條件地從指定的位置指令而不是控制轉移指令的下一條指令繼續執行程式,從概念模型上理解,可以認為控制轉移指令就是在有條件或無條件地修改 PC 暫存器的值。控制轉移指令如下。

  • 條件分支:ifeq、iflt、ifle、ifne、ifgt、ifge、ifnull、ifnonnull、if_icmpeq、if_icmpne、if_icmplt、if_icmpgt、if_icmple、if_icmpge、if_acmpeq 和 if_acmpne。
  • 複合條件分支:tableswitch、lookupswitch。
  • 無條件分支:goto、goto_w、jsr、jsr_w、ret。

        在 Java 虛擬機器中有專門的指令集用來處理 int 和 reference 型別的條件分支比較操作,為了可以無須明顯標識一個實體值是否 null,也有專門的指令用來檢測 null 值。

        與前面算術運算是的規則一致,對於 boolean 型別、byte 型別、char 型別和 short 型別的條件分支比較操作,都是使用 int 型別的比較指令來完成,而對於 long 型別、float 型別和 double 型別的條件分支比較操作,則會先執行相應型別的比較運算指令(dcmpg、dcmpl、fcmpg、fcmpl、lcmp),運算指令會返回一個整形值到運算元棧中,隨後再執行 int 型別的條件分支比較操作來完成整個分支跳轉。由於各種型別的比較最終都會轉化為 int 型別的比較操作,int 型別比較是否方便完善就顯得尤為重要,所以 Java 虛擬機器提供的 int 型別的條件分支指令是最為豐富和強大的。

方法呼叫和返回指令

        方法呼叫(分派、執行過程),先列舉以下 5 條用於方法呼叫的指令。

  • invokevirtual    指令用於呼叫物件的例項方法,根據物件的實際型別進行分派(虛方法分派),這也是 Java 語言中最常見的方法分派方式。
  • invokeinterface    指令用於呼叫介面方法,它會在執行時搜尋一下實現了這個介面方法的物件,找出適合的方法進行呼叫。
  • invokespecial    指令用於呼叫一些需要特殊處理的例項方法,包括例項初始化方法、私有方法和父類方法。
  • invokestatic    指令用於呼叫類方法(static 方法)。
  • invokedynamic    指令用於在執行時動態解析出呼叫點限定符所引用的方法,並執行該方法,前面 4 條呼叫指令的分派邏輯都固化在 Java 虛擬機器內部,而 invokedynamic 指令的分派邏輯是由使用者所設定的引導方法決定的。
        方法呼叫指令與資料型別無關,而方法返回指令是根據返回值的型別區分的,包括 ireturn(當返回值是 boolean、byte、char、short 和 int 型別時使用)、lreturn、freturn、dreturn 和 areturn,另外還有一條return 指令共宣告為 void 的方法、例項初始化方法以及類和介面的類初始化方法使用。

異常處理指令

        在 Java 程式中顯式丟擲異常的操作(throw 語句)都由 athrow 指令來實現,除了用 throw 語句顯式丟擲異常情況之外,Java 虛擬機器規範還規定了許多執行時異常會在其他 Java 虛擬機器指令檢測到異常狀況時自動丟擲。例如,在前面介紹的整數運算中,當除數為零時,虛擬機器會在 idiv 或 ldiv 指令中丟擲 ArithmeticException 異常。

        而在 Java 虛擬機器中,處理異常(catch 語句)不是由位元組碼指令來實現的(很久之前曾經使用 jsr 和 ret 指令來實現,現在已經不用了),而是採用異常表來完成的。

同步指令

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

        方法級的同步是隱式的,即無須通過位元組碼指令來控制,它實現在方法呼叫和返回操作之中。虛擬機器可以從方法常量池的方法表結構中的 ACC_SYNCHRONIZED 方法標誌得知一個方法是否宣告為同步方法。當方法呼叫時,呼叫指令將會檢查方法的 ACC_SYNCHRONIZED 訪問標誌是否被設定,如果設定了,執行執行緒就要求先成功持有管程,然後才能執行方法,最後當方法完成(無論是正常完成還是非正常完成)時釋放管程。在方法執行期間,執行執行緒持有了管程,其他任何執行緒都無法再獲取到同一個管程。如果一個同步方法執行期間丟擲了異常,並且在方法內部無法處理此異常,那麼這個同步方法所持有的管程將在異常拋到同步方法之外時自動釋放。

        同步一段指令集序列通常是由 Java 語言中的 synchronized 語句塊來表示的,Java 虛擬機器的指令集中有 monitorenter 和 monitorexit 兩條指令來支援 synchronized 關鍵字的語義,正確實現 synchronized 關鍵字需要 javac 編譯器與 Java 虛擬機器兩者共同協作支援,譬如程式碼清單 6-6 中所示的程式碼。

程式碼清單 6-6  程式碼同步演示

        編譯後,這段程式碼生成的位元組碼序列如下:

        編譯器必須確保無論方法通過何種方式完成,方法中呼叫過的每條 monitorenter 指令都必須執行其對應的 monitorexit 指令,而無論這個方法是正常結束還是異常結束。

        從程式碼清單 6-6 的位元組碼序列中可以看到,為了保證在方法異常完成時 monitorenter 和 monitorexit 指令依然可以正確配對執行,編譯器會自動產生一個異常處理器,這個異常處理器宣告可處理所有的異常,它的目的就是用來執行 monitorexit 指令。

相關推薦

深入理解java虛擬機器(六)位元組指令簡介

Java虛擬機器指令是由(佔用一個位元組長度、代表某種特定操作含義的數字)操作碼Opcode,以及跟隨在其後的零至多個代表此操作所需引數的稱為運算元 Operands 構成的。由於Java虛擬機器是面向運算元棧而不是暫存器的架構,所以大多數指令都只有操作碼,而沒有運算元。 位元組碼指令集是一種具有鮮明特點、

深入理解JVM虛擬機器(五):位元組指令簡介

Java 虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的數字(稱為操作碼)以及跟隨其後的零至多個代表此操作所需引數(運算元)而構成。由於 Java 虛擬機器採用面向運算元棧而不是暫存器的架構,所以大多數的指令都不包含運算元,只有一個操作碼。 1. 位元組碼與資料型別

位元組指令簡介

摘自《深入理解 Java 虛擬機器:JVM 高階特性與最佳實踐》(第二版)         Java 虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的數字(稱為操作碼,Opcode)以及跟隨其後的零至多個代表此操作所需引數(稱為運算元,Operands)而構成。由

10 位元組指令簡介

《深入理解Java虛擬機器:JVM高階特性與最佳實踐(第2版)》6.4節 長度:1個位元組 總數:<=256 面向:運算元棧,而非暫存器 對齊:運算元長度不對齊 操作碼助記符:i代表int,l代表long,s代表short,b代表byte,c代表char,f代表fl

JVM之位元組指令簡介

java虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的數字以及跟隨其後的零至多個代表此操作所需的引數而構成的。 位元組碼與資料型別 載入和儲存指令: 將資料在棧幀中的區域性變量表和運算元棧

位元組指令簡介

        Java虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的數字(稱為操作碼,Pocode)以及跟隨其後的零至多個代表此操作所需引數(稱為運算元,Operands)而構成。由於Java虛擬機器採用面向運算元棧而不是暫存器的架構,所以大多數的指令都不包含

[四] java虛擬機器JVM編譯器編譯程式碼簡介 位元組指令例項 程式碼到底編譯成了什麼形式

public static void main(String[] args) { boolean bNum = true; char cNum = 2; byte byteNum = 127; short sNum = 32767; int iNum = 100; long lNum =

JVM位元組指令簡介

Java 虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的操作碼(Opcode)以及跟隨其後的零至多個代表此操作所需引數的運算元(Operands)所構成。虛擬機器中許多指令並不包含運算元,只有一個操作碼。 如果忽略異常處理,那 Java 虛擬機器的直譯器使用下

Oracle數據庫代指令簡介

ever others ref shu varchar2 extend manage 20M 函數計算 這是oracle的課後作業,弄懂這些也差不多了吧,不懂的可以去看我的SQL sever數據庫的博客那個寫的詳細。視頻以後有時間錄~ 登錄數據庫 //方法一 s

JVM總括三-位元組位元組指令、JIT編譯執行

JVM總括三-位元組碼、位元組碼指令、JIT編譯執行     java檔案編譯後的class檔案,java跨平臺的中間層,JVM通過對位元組碼的解釋執行(執行模式,還有JIT編譯執行,下面講解),遮蔽對作業系統的依賴。一個位元組(8位)可以儲存256中不同的指令,這樣的指令就是位元組碼,ja

大話+圖說:Java位元組指令——只為讓你懂

前言 隨著Java開發技術不斷被推到新的高度,對於Java程式設計師來講越來越需要具備對更深入的基礎性技術的理解,比如Java位元組碼指令。不然,可能很難深入理解一些時下的新框架、新技術,盲目一味追新也會越來越感乏力。 本文既不求照本宣科,亦不求炫技或著文立說,僅力圖以最簡明、最形象生動的方式,結合例子與

JVM 虛擬機器位元組指令

把JVM虛擬機器位元組指令表整理了一下,方便搜尋,偶爾複習下 純手工整理,可能存在一些問題,如果發現請及時告之我會修正 位元組碼 助記符 指令含義 0x00 nop None 0x01

class檔案結構與jvm位元組指令

https://blog.csdn.net/luckydog1991/article/details/51654964這篇文章詳細的介紹了class檔案和位元組碼指令 Class檔案結構 https://blog.csdn.net/tyrone1979/article/details/9

Java位元組指令收集大全

Java位元組碼指令大全 常量入棧指令 指令碼 操作碼(助記符) 運算元 描述(棧指運算元棧) 0x01 aconst_null  

Java位元組詳解(三)位元組指令(轉)

一、概述 Java虛擬機器採用基於棧的架構,其指令由操作碼和運算元組成。 操作碼:一個位元組長度(0~255),意味著指令集的操作碼個數不能操作256條。 運算元:一條指令可以有零或者多個運算元,且運算元可以是1個或者多個位元組。編譯後的程式碼沒有采用運算元長

JVM學習筆記1:位元組指令

一.位元組碼指令集簡介: Java虛擬機器的指令由一個位元組長度的、代表著某種特定操作含義的操作碼(opcode)以及跟隨其後的零至多個代表此操作所需引數的運算元(operand)所構成。虛擬機器中許多指令並不包含運算元,只有一個操作碼。 如果忽略異常處理,那麼java虛

[三] java虛擬機器 JVM位元組 指令集 bytecode 操作 指令分類用法 助記符

上面關於dup的描述摘自 虛擬機器規範,很難理解看起來是非常難以理解的,不妨換一個角度我們知道區域性變數的空間分配分為兩種long 和 double 佔用2個slot  其他佔用一個運算元棧,每個單位可以表示虛擬機器支援的任何的一個數據型別不過運算元棧其實同區域性變數一樣,他也是被組織一個數組, 每個元素的資

JVM九:class位元組指令

一:位元組碼與資料型別     Java虛擬機器的指令由一個位元組長度,代表著某種特定操作含義的數字(稱為操作碼)以及跟其隨後的零至多個代表此操作所需引數(稱為運算元)而構成。Java虛擬機器採用面向運算元棧而不是暫存器的架構,所以大多數指令都不包含運算元。因為位元

位元組指令看重寫在JVM中的實現

        Java是解釋執行的,包括動態連結的特性,都給解析或執行期間提供了很多靈活擴充套件的空間。面嚮物件語言的繼承、封裝和多型的特性,在JVM中是怎樣進行編譯、解析,以及通過位元組碼指令如何確定方法呼叫的版本是本文如下要探討的主要內容,全文圍繞一個多型的簡單舉例來

Python 2.6.2的位元組指令集一覽

對Python的位元組碼指令集感興趣但不知道從何下手麼?執行這段程式碼就能看到位元組碼的列表:  Python程式碼   import opcode   for op in range(len(opcode.opname)):     print('0x%.2X(%