一般設計
- 機器模型和呼叫慣例旨在模仿常見的實際架構和 C 樣式呼叫慣例:
- 機器是根據註冊建立,因此建立時會固定影格大小。每個影格都包含特定數量的註冊器 (由方法指定),以及執行方法所需的任何附加資料,例如 (但不限於) 程式計數器和包含方法的 .dex檔案參照。
- 當用於位元值 (例如整數和浮點數) 時,寄存器的寬度會視為 32 位元。相鄰的註冊組合用於 64 位元值。註冊組不須對齊。
- 當用於物件參照時,註冊的寬度足以容納一項此類參照。
- 就位元表示法而言,(Object) null == (int) 0。
- 方法的 N 引數會依序放置在方法呼叫結構體的最後 N 暫存器中。寬引數會消耗兩個註冊。例項方法會傳遞 this參照做為第一個引數。
 
- 機器是根據註冊建立,因此建立時會固定影格大小。每個影格都包含特定數量的註冊器 (由方法指定),以及執行方法所需的任何附加資料,例如 (但不限於) 程式計數器和包含方法的 
- 指令串流中的儲存單位是 16 位元無符號數量。部分指令中的某些位元會遭到忽略 / 必須為零。
- 指令不會無故限制為特定類型。舉例來說,如果指令是移動 32 位元註冊值而無需解讀,則不必指定是否要移動 int 或浮點值。
- 針對字串、類型、欄位和方法的參照,會分別列舉並編入索引的常數集區。
- 位元值文字資料會在指令串流中內嵌表示。
- 因為在實際情況下,方法需要超過 16 個註冊的情況並不常見,而且需要超過八個註冊的情況相當常見,因此許多指令都只會處理前 16 個註冊。在合理可行情況下,指令可參照前 256 個寄存器。此外,部分指令具有可支援更大暫存器數量的變化版本,包括一組萬用 move指令,可處理v0至v65535範圍內的暫存器。如果指令變化版本無法處理所需的暫存器,則暫存器內容會從原始暫存器移至低暫存器 (在作業前),以及/或者從低結果暫存器移至高暫存器 (在作業後)。
- 有幾個「偽指令」用於保存變長資料酬載,並由一般指令 (例如 fill-array-data) 參照。在執行的正常流程中,絕對不會遇到這類指令。此外,指令必須位於偶數位元組碼偏移位置 (也就是 4 位元組對齊)。為了符合這項要求,如果這類指令無法對齊,則 dex 產生工具必須以間隔符號的形式發出額外的nop指令。最後,雖然並非必要,但大多數工具都會選擇在方法結尾處發出這些指令,因為如果不這樣做,可能就需要額外指令來分支。
- 在執行中的系統上安裝時,部分指令可能會變更格式,以便進行安裝時的靜態連結最佳化。這樣一來,一旦連結關係明確,就能加快執行速度。如要查看建議的變化版本,請參閱相關的指示格式文件。我們謹慎使用「建議」一詞,因為這些做法並非強制規定。
- 人性化語法和助憶法:
  - 引數的「Dest-then-source」排序。
- 部分 Opcode 具有可區分的名稱後置字元,用於指出其運算的類型:
    - 類型通用 32 位元操作碼未標示。
- 類型一般 64 位元 Opcode 的後置字串為 -wide。
- 類型專屬的 Opcode 會加上其類型 (或簡單的縮寫) 做為後置字元,包括:-boolean、-byte、-char、-short、-int、-long、-float、-double、-object、-string、-class和-void。
 
- 部分 Opcode 會附上可區分的副檔名,以便區分具有不同指令版面配置或選項的相同運算。這些後置字串會以斜線 (「/」) 與主要名稱分隔,主要目的是讓產生及解讀可執行檔的程式碼中,靜態常數與一對一對應,以減少人為的模糊性。
- 在本說明中,每四位元寬度使用一個字元來強調值的寬度 (例如常數的範圍或可能位址的暫存器數量)。
- 例如在「move-wide/from16 vAA, vBBBB」指令中:- 「move」是基本運算碼,表示基本運算 (移動註冊值)。
- 「wide」是名稱後置字串,表示該函式會處理寬 (64 位元) 資料。
- 「from16」是運算碼後置字元,表示變體會將 16 位元註冊參照做為來源。
- 「vAA」是目的地暫存器 (由作業隱含;再次提醒,規則是目的地引數一律會先出現),必須位於v0至v255的範圍內。
- 「vBBBB」是來源登錄,必須位於v0到v65535的範圍內。
 
- 「
 
- 如要進一步瞭解各種指令格式 (列於「運算元式與格式」下方),以及運算碼語法的詳細資訊,請參閱指令格式說明文件。
- 如要進一步瞭解位元碼在整體架構中的適當位置,請參閱 .dex檔案格式說明文件。
位元碼集摘要
| 作業與格式 | 助憶法 / 語法 | 引數 | 說明 | 
|---|---|---|---|
| 00 10x | nop | 浪費週期。 注意:含有資料的疑似指令會加上這個運算碼,在這種情況下,運算碼單位的高位元組會指出資料的性質。請參閱下方的「 | |
| 01 12x | move vA, vB | A:目的地暫存器 (4 位元)B:來源暫存器 (4 位元) | 將一個非物件型註冊器的內容移至另一個註冊器。 | 
| 02 22x | move/from16 vAA, vBBBB | A:目的地暫存器 (8 位元)B:來源暫存器 (16 位元) | 將一個非物件型註冊器的內容移至另一個註冊器。 | 
| 03 32x | move/16 vAAAA, vBBBB | A:目的地暫存器 (16 位元)B:來源暫存器 (16 位元) | 將一個非物件型註冊器的內容移至另一個註冊器。 | 
| 04 12x | move-wide vA, vB | A:目的地暫存器組 (4 位元)B:來源暫存器組 (4 位元) | 將一個註冊組合的內容移至另一個註冊組合。 注意:從  | 
| 05 22x | move-wide/from16 vAA, vBBBB | A:目的地暫存器組 (8 位元)B:來源暫存器組 (16 位元) | 將一個註冊組合的內容移至另一個註冊組合。 注意:導入方面的注意事項與上述  | 
| 06 32x | move-wide/16 vAAAA, vBBBB | A:目的地暫存器組 (16 位元)B:來源暫存器組 (16 位元) | 將一個註冊組合的內容移至另一個註冊組合。 注意:導入方面的注意事項與上述  | 
| 07 12x | move-object vA, vB | A:目的地暫存器 (4 位元)B:來源暫存器 (4 位元) | 將一個含有物件的註冊表內容移至另一個註冊表。 | 
| 08 22x | move-object/from16 vAA, vBBBB | A:目的地暫存器 (8 位元)B:來源暫存器 (16 位元) | 將一個含有物件的註冊表內容移至另一個註冊表。 | 
| 09 32x | move-object/16 vAAAA, vBBBB | A:目的地暫存器 (16 位元)B:來源暫存器 (16 位元) | 將一個含有物件的註冊表內容移至另一個註冊表。 | 
| 0a 11x | move-result vAA | A:目的地暫存器 (8 位元) | 將最近一次 invoke-kind的單字非物件結果移至指定的註冊表。這項操作必須在invoke-kind之後立即執行,且該invoke-kind的 (單字、非物件) 結果不得忽略;其他位置均無效。 | 
| 0b 11x | move-result-wide vAA | A:目的地暫存器組 (8 位元) | 將最近 invoke-kind的雙字結果移至指定的註冊組。這項操作必須在invoke-kind之後立即執行,且該指令的 (雙字) 結果不得忽略;其他位置皆無效。 | 
| 0c 11x | move-result-object vAA | A:目的地暫存器 (8 位元) | 將最近一次 invoke-kind的物件結果移至指定的註冊表。這項操作必須在invoke-kind或filled-new-array之後立即執行,且不應忽略其 (物件) 結果;否則其他位置均無效。 | 
| 0d 11x | move-exception vAA | A:目的地暫存器 (8 位元) | 將剛捕獲的例外狀況儲存到指定的註冊表中。這必須是任何例外狀況處理常式的首要指令,且所捕獲的例外狀況不得遭到忽略,且此指令「只能」以例外狀況處理常式的首要指令出現,其他位置皆無效。 | 
| 0e 10x | return-void | 從 void方法傳回。 | |
| 0f 11x | return vAA | A:傳回值登錄器 (8 位元) | 從單寬 (32 位元) 非物件值傳回方法傳回。 | 
| 10 11x | return-wide vAA | A:傳回值暫存器組 (8 位元) | 從傳回值的雙寬 (64 位元) 方法傳回。 | 
| 11 11x | return-object vAA | A:傳回值暫存器 (8 位元) | 從物件傳回方法傳回。 | 
| 12 11n | const/4 vA, #+B | A:目的地暫存器 (4 位元)B:已簽署的 int (4 位元) | 將指定的字面值 (已延伸至 32 位元的符號) 移至指定的註冊器。 | 
| 13 21 秒 | const/16 vAA, #+BBBB | A:目的地暫存器 (8 位元)B:已簽署的 int (16 位元) | 將指定的字面值 (已延伸至 32 位元的符號) 移至指定的註冊器。 | 
| 14 31i | const vAA, #+BBBBBBBB | A:目的地暫存器 (8 位元)B:任意 32 位元常數 | 將指定的常值移至指定的註冊器。 | 
| 15 21h | const/high16 vAA, #+BBBB0000 | A:目的地暫存器 (8 位元)B:已簽署的 int (16 位元) | 將指定的字面值 (右零擴展至 32 位元) 移至指定的註冊器。 | 
| 16 21 秒 | const-wide/16 vAA, #+BBBB | A:目的地暫存器 (8 位元)B:已簽署的 int (16 位元) | 將指定的字面值 (已擴充至 64 位元的符號) 移至指定的寄存器組。 | 
| 17 31i | const-wide/32 vAA, #+BBBBBBBB | A:目的地暫存器 (8 位元)B:已簽署的 int (32 位元) | 將指定的字面值 (已擴充至 64 位元的符號) 移至指定的寄存器組。 | 
| 18 51l | const-wide vAA, #+BBBBBBBBBBBBBBBB | A:目的地暫存器 (8 位元)B:任意雙寬 (64 位元) 常數 | 將指定的常值移至指定的暫存器組。 | 
| 19 21h | const-wide/high16 vAA, #+BBBB000000000000 | A:目的地暫存器 (8 位元)B:已簽署的 int (16 位元) | 將指定的字面值 (右零延伸至 64 位元) 移至指定的寄存器組。 | 
| 1a 21c | const-string vAA, string@BBBB | A:目的地暫存器 (8 位元)B:字串索引 | 將參照由指定索引指定的字串移至指定的註冊器。 | 
| 1b 31c | const-string/jumbo vAA, string@BBBBBBBB | A:目的地暫存器 (8 位元)B:字串索引 | 將參照由指定索引指定的字串移至指定的註冊器。 | 
| 1c 21c | const-class vAA, type@BBBB | A:目的地暫存器 (8 位元)B:型別索引 | 將參照指定索引所指定類別的參照移至指定的註冊器。如果指定的類型為基本類型,這會儲存基本類型的退化類別參照。 | 
| 1d 11x | monitor-enter vAA | A:參照含有註冊 (8 位元) | 取得指定物件的監控器。 | 
| 1e 11x | monitor-exit vAA | A:參照含有註冊 (8 位元) | 釋出指定物件的監控器。 注意:如果這個指令需要擲回例外狀況,則必須以 PC 已進展到指令後的狀態擲回。您或許可以將這視為指令已成功執行 (在某種意義上),而例外狀況是在指令「後」,但在下一個指令有機會執行之前發生。這個定義可讓方法使用監控清理萬用字 (例如 | 
| 1f 21c | check-cast vAA, type@BBBB | A:參照含有登錄器 (8 位元)B:型別索引 (16 位元) | 如果指定登錄表中的參照無法轉換為指定類型,則會擲回 ClassCastException。注意:由於  | 
| 20 22c | instance-of vA, vB, type@CCCC | A:目的地暫存器 (4 位元)B:參照暫存器 (4 位元)C:類型索引 (16 位元) | 如果指定的參照是指定類型的例項,則儲存在指定目的地註冊 1中;如果不是,則儲存在0中。注意:由於  | 
| 21 12x | 陣列長度 vA、vB | A:目的地暫存器 (4 位元)B:陣列參照暫存器 (4 位元) | 在指定目的地註冊中儲存指定陣列的長度,以項目為單位 | 
| 22 21c | new-instance vAA, type@BBBB | A:目的地暫存器 (8 位元)B:型別索引 | 建構指定類型的新例項,並在目的地儲存對該例項的參照。類型必須參照非陣列類別。 | 
| 23 22c | new-array vA, vB, type@CCCC | A:目的地暫存器 (4 位元)B:大小暫存器C:類型索引 | 建構指定類型和大小的新陣列。類型必須是陣列類型。 | 
| 24 35c | 已填入的陣列 {vC, vD, vE, vF, vG},類型@BBBB | A:陣列大小和引數字詞數量 (4 位元)B:型別索引 (16 位元)C..G:引數註冊 (每個 4 位元) | 建構指定類型和大小的陣列,並以提供的內容填入陣列。類型必須是陣列類型。陣列的內容必須是單字 (也就是沒有 long或double的陣列,但參照類型是可接受的)。建構的例項會以「結果」的形式儲存,這與方法叫用指示的儲存結果方式相同,因此建構的例項必須透過後續的move-result-object指示 (如果要使用) 移至寄存器。 | 
| 25 3rc | 已填入的陣列/範圍 {vCCCC .. vNNNN},型別@BBBB | A:陣列大小和引數字節數 (8 位元)B:型別索引 (16 位元)C:第一個引數註冊 (16 位元)N = A + C - 1 | 建構指定類型和大小的陣列,並以提供的內容填入陣列。說明和限制與上述 filled-new-array相同。 | 
| 26 31t | fill-array-data vAA, +BBBBBBBB (附加資料,如下方「 fill-array-data-payload格式」所述) | A:陣列參照 (8 位元)B:以表格資料虛擬指令為基準的帶正號「分支」偏移量 (32 位元) | 使用指定資料填入指定陣列。參照項目必須是原始類型的陣列,且資料表格必須與其類型相符,且所含元素不得超過陣列可容納的數量。也就是說,陣列可能比資料表大,如果是這種情況,系統只會設定陣列的初始元素,而不會處理其餘元素。 | 
| 27 11x | 擲回 vAA | A:例外狀況含有暫存器 (8 位元) | 擲回指定的例外狀況。 | 
| 28 10t | goto +AA | A:有符號分支偏移量 (8 位元) | 無條件跳到指定的指令。 注意:分支偏移值不得為  | 
| 29 20t | goto/16 +AAAA | A:帶符號分支偏移量 (16 位元) | 無條件跳到指定的指令。 注意:分支偏移值不得為  | 
| 2a 30t | goto/32 +AAAAAAAA | A:已簽署的分支偏移 (32 位元) | 無條件跳到指定的指令。 | 
| 2b 31t | packed-switch vAA, +BBBBBBBB (附加資料請參閱下方的「 packed-switch-payload格式」) | A:註冊以測試B:已簽署的「分支」偏移至表格資料的疑似指令 (32 位元) | 根據指定寄存器中的值,使用對應特定整數範圍中每個值的偏移量表格,跳至新的指令,或在沒有相符項目時,跳至下一個指令。 | 
| 2c 31t | sparse-switch vAA, +BBBBBBBB (附加資料請參閱下方的「 sparse-switch-payload格式」) | A:註冊以測試B:已簽署的「分支」偏移量,可用於表格資料的疑似指令
    (32 位元) | 根據指定登錄器中的值,使用值-偏移量組合的排序表跳至新指令,或在沒有相符項目時跳至下一個指令。 | 
| 2d..31 23x | cmpkind vAA、vBB、vCC 2d: cmpl-float (lt bias) 2e: cmpg-float (gt bias) 2f: cmpl-double (lt bias) 30: cmpg-double (gt bias) 31: cmp-long | A:目的地暫存器 (8 位元)B:第一個來源暫存器或組C:第二個來源暫存器或組 | 執行指定的浮點或 long比較作業,如果是b == c,請將a設為0;如果是b > c,請設為1;如果是b < c,請設為-1。浮點運算所列的「偏差」會指出NaN比較的處理方式:如果是「gt bias」,指令會針對NaN比較傳回1;如果是「lt bias」,則會傳回-1。舉例來說,如要檢查浮點  | 
| 32..37 22t | if-test vA, vB, +CCCC 32: if-eq 33: if-ne 34: if-lt 35: if-ge 36: if-gt 37: if-le | A:要測試的第一個暫存器 (4 位元)B:要測試的第二個暫存器 (4 位元)C:帶符號分支偏移量 (16 位元) | 如果指定的兩個註冊值符合指定的比較條件,則分支至指定的目的。 注意:分支偏移值不得為  | 
| 38..3d 21t | if-testz vAA, +BBBB 38: if-eqz 39: if-nez 3a: if-ltz 3b: if-gez 3c: if-gtz 3d: if-lez | A:要測試的註冊 (8 位元)B:有符號分支偏移量 (16 位元) | 如果指定的註冊器值與指定的 0 比較,則分支至指定的目的。 注意:分支偏移值不得為  | 
| 3e..43 10x | (未使用) | (未使用) | |
| 44..51 23x | arrayop vAA、vBB、vCC 44: aget 45: aget-wide 46: aget-object 47: aget-boolean 48: aget-byte 49: aget-char 4a: aget-short 4b: aput 4c: aput-wide 4d: aput-object 4e: aput-boolean 4f: aput-byte 50: aput-char 51: aput-short | A:值登錄器或組合;可能是來源或目的地 (8 位元)B:陣列登錄器 (8 位元)C:索引登錄器 (8 位元) | 在指定陣列的指定索引處執行已識別的陣列運算,並將值載入或儲存至值登錄。 | 
| 52..5f 22c | iinstanceop vA, vB, field@CCCC 52: iget 53: iget-wide 54: iget-object 55: iget-boolean 56: iget-byte 57: iget-char 58: iget-short 59: iput 5a: iput-wide 5b: iput-object 5c: iput-boolean 5d: iput-byte 5e: iput-char 5f: iput-short | A:值登錄或組合;可能是來源或目的地 (4 位元)B:物件登錄 (4 位元)C:例項欄位參照索引 (16 位元) | 使用已識別的欄位,執行已識別的物件執行個體欄位作業,並載入或儲存至值登錄。 注意:這些 Opcode 是靜態連結的合理候選項目,可將欄位引數改為更直接的偏移值。 | 
| 60..6d 21c | sstaticop vAA, field@BBBB 60: sget 61: sget-wide 62: sget-object 63: sget-boolean 64: sget-byte 65: sget-char 66: sget-short 67: sput 68: sput-wide 69: sput-object 6a: sput-boolean 6b: sput-byte 6c: sput-char 6d: sput-short | A:值登錄或組合;可能是來源或目的地 (8 位元)B:靜態欄位參照索引 (16 位元) | 使用已識別的靜態欄位,執行已識別的物件靜態欄位作業,並載入或儲存至值登錄。 注意:這些 Opcode 是靜態連結的合理候選項目,可將欄位引數改為更直接的偏移值。 | 
| 6e..72 35c | invoke-kind {vC, vD, vE, vF, vG}, meth@BBBB 6e: invoke-virtual 6f: invoke-super 70: invoke-direct 71: invoke-static 72: invoke-interface | A:引數字詞數量 (4 位元)B:方法參照索引 (16 位元)C..G:引數暫存器 (每個 4 位元) | 呼叫指定的方法。結果 (如有) 可能會與適當的 move-result*變體一併儲存,做為後續立即執行的指令。
 當  在 DEX 檔案  
 
 
 注意:這些 Opcode 是靜態連結的合理候選項目,可將方法引數改為更直接的偏移值 (或其組合)。 | 
| 73 10x | (未使用) | (未使用) | |
| 74..78 3rc | invoke-kind/range {vCCCC .. vNNNN}, meth@BBBB 74: invoke-virtual/range 75: invoke-super/range 76: invoke-direct/range 77: invoke-static/range 78: invoke-interface/range | A:引數字數 (8 位元)B:方法參照索引 (16 位元)C:第一個引數註冊 (16 位元)N = A + C - 1 | 呼叫指定的方法。如需詳細資訊、注意事項和建議,請參閱上述第一個 invoke-kind說明。 | 
| 79..7a 10x | (未使用) | (未使用) | |
| 7b..8f 12x | unop vA, vB 7b: neg-int 7c: not-int 7d: neg-long 7e: not-long 7f: neg-float 80: neg-double 81: int-to-long 82: int-to-float 83: int-to-double 84: long-to-int 85: long-to-float 86: long-to-double 87: float-to-int 88: float-to-long 89: float-to-double 8a: double-to-int 8b: double-to-long 8c: double-to-float 8d: int-to-byte 8e: int-to-char 8f: int-to-short | A:目的地暫存器或組合 (4 位元)B:來源暫存器或組合 (4 位元) | 對來源暫存器執行已識別的單一運算,並將結果儲存在目的地暫存器中。 | 
| 90..af 23x | binop vAA, vBB, vCC 90: add-int 91: sub-int 92: mul-int 93: div-int 94: rem-int 95: and-int 96: or-int 97: xor-int 98: shl-int 99: shr-int 9a: ushr-int 9b: add-long 9c: sub-long 9d: mul-long 9e: div-long 9f: rem-long a0: and-long a1: or-long a2: xor-long a3: shl-long a4: shr-long a5: ushr-long a6: add-float a7: sub-float a8: mul-float a9: div-float aa: rem-float ab: add-double ac: sub-double ad: mul-double ae: div-double af: rem-double | A:目的地暫存器或組 (8 位元)B:第一個來源暫存器或組 (8 位元)C:第二個來源暫存器或組 (8 位元) | 對兩個來源暫存器執行已識別的二進位運算,並將結果儲存在目的地暫存器中。 注意:與其他  | 
| b0..cf 12x | binop/2addr vA, vB b0: add-int/2addr b1: sub-int/2addr b2: mul-int/2addr b3: div-int/2addr b4: rem-int/2addr b5: and-int/2addr b6: or-int/2addr b7: xor-int/2addr b8: shl-int/2addr b9: shr-int/2addr ba: ushr-int/2addr bb: add-long/2addr bc: sub-long/2addr bd: mul-long/2addr be: div-long/2addr bf: rem-long/2addr c0: and-long/2addr c1: or-long/2addr c2: xor-long/2addr c3: shl-long/2addr c4: shr-long/2addr c5: ushr-long/2addr c6: add-float/2addr c7: sub-float/2addr c8: mul-float/2addr c9: div-float/2addr ca: rem-float/2addr cb: add-double/2addr cc: sub-double/2addr cd: mul-double/2addr ce: div-double/2addr cf: rem-double/2addr | A:目的地和第一個來源暫存器或組合 (4 位元)B:第二個來源暫存器或組合 (4 位元) | 對兩個來源暫存器執行已識別的二進位運算,並將結果儲存在第一個來源暫存器中。 注意:與其他  | 
| d0..d7 22 秒 | binop/lit16 vA, vB, #+CCCC d0: add-int/lit16 d1: rsub-int (reverse subtract) d2: mul-int/lit16 d3: div-int/lit16 d4: rem-int/lit16 d5: and-int/lit16 d6: or-int/lit16 d7: xor-int/lit16 | A:目的地暫存器 (4 位元)B:來源暫存器 (4 位元)C:已簽署的 int 常數 (16 位元) | 在指定的登錄器 (第一個引數) 和文字值 (第二個引數) 上執行指定的二元運算,並將結果儲存在目的地登錄器中。 注意:
     | 
| d8..e2 22b | binop/lit8 vAA, vBB, #+CC d8: add-int/lit8 d9: rsub-int/lit8 da: mul-int/lit8 db: div-int/lit8 dc: rem-int/lit8 dd: and-int/lit8 de: or-int/lit8 df: xor-int/lit8 e0: shl-int/lit8 e1: shr-int/lit8 e2: ushr-int/lit8 | A:目的地暫存器 (8 位元)B:來源暫存器 (8 位元)C:已簽署的 int 常數 (8 位元) | 在指定的登錄器 (第一個引數) 和文字值 (第二個引數) 上執行指定的二元運算,並將結果儲存在目的地登錄器中。 注意:如要進一步瞭解  | 
| e3..f9 10 倍 | (未使用) | (未使用) | |
| fa 45cc | invoke-polymorphic {vC, vD, vE, vF, vG}, meth@BBBB, proto@HHHH | A:引數字節數 (4 位元)B:方法參照索引 (16 位元)C:接收器 (4 位元)D..G:引數暫存器 (每個 4 位元)H:原型參照索引 (16 位元) | 叫用指定簽章多型別方法。結果 (如有) 可能會與適當的 move-result*變化版本一併儲存,做為後續立即執行的指令。方法參照必須是簽章多型態方法,例如 java.lang.invoke.MethodHandle.invoke或java.lang.invoke.MethodHandle.invokeExact。接收器必須是支援所要叫用的簽章多型態方法的物件。 原型參照會說明提供的引數類型和預期的傳回類型。 invoke-polymorphic位元碼在執行時可能會發生例外狀況。針對所叫用的簽名多型別方法,API 說明文件會說明這些例外狀況。從 038版起,會出現在 Dex 檔案中。 | 
| fb 4rcc | invoke-polymorphic/range {vCCCC .. vNNNN}, meth@BBBB, proto@HHHH | A:引數字數 (8 位元)B:方法參照索引 (16 位元)C:接收器 (16 位元)H:原型參照索引 (16 位元)N = A + C - 1 | 叫用指定的方法句柄。詳情請參閱上方的 invoke-polymorphic說明。從 038版起,會出現在 Dex 檔案中。 | 
| fc 35c | invoke-custom {vC, vD, vE, vF, vG}, call_site@BBBB | A:引數字詞數量 (4 位元)B:呼叫網站參照索引 (16 位元)C..G:引數暫存器 (每個 4 位元) | 解析並叫用指定的呼叫網址。叫用作業的結果 (如有) 可能會與適當的 move-result*變化版本一併儲存,做為後續指令。この命令會在兩個階段執行:呼叫網址解析和呼叫網址叫用。 呼叫端點解析會檢查指定的呼叫端點是否有相關聯的 java.lang.invoke.CallSite例項。如果沒有,系統會使用 DEX 檔案中的引數,叫用指定呼叫網址的啟動連結器方法 (請參閱 call_site_item)。引導程式連結器方法會傳回java.lang.invoke.CallSite例項,如果沒有關聯,則會與指定的呼叫網址建立關聯。另一個執行緒可能已先建立關聯,如果是這樣,指令的執行作業會繼續使用第一個關聯的java.lang.invoke.CallSite例項。呼叫網站呼叫會在已解析 java.lang.invoke.CallSite例項的java.lang.invoke.MethodHandle目標上執行。如果使用方法句柄和invoke-custom指令的引數,以確切方法句柄叫用方式執行invoke-polymorphic(如上所述),系統就會叫用目標。引導程式連結器方法所產生的例外狀況會包裝在 java.lang.BootstrapMethodError中。如果符合下列條件,系統也會擲回BootstrapMethodError:
 038版起,會出現在 Dex 檔案中。 | 
| fd 3rc | invoke-custom/range {vCCCC .. vNNNN}, call_site@BBBB | A:引數字數 (8 位元)B:呼叫網站參照索引 (16 位元)C:第一個引數註冊 (16 位元)N = A + C - 1 | 解析並叫用呼叫位置。詳情請參閱上方的 invoke-custom說明。從 038版起,會出現在 Dex 檔案中。 | 
| fe 21c | const-method-handle vAA, method_handle@BBBB | A:目的地登錄 (8 位元)B:方法句柄索引 (16 位元) | 將參照由指定索引指定的方法句柄移至指定的註冊器。 從 039版起,會出現在 Dex 檔案中。 | 
| ff 21c | const-method-type vAA, proto@BBBB | A:目的地註冊 (8 位元)B:方法原型參考資料 (16 位元) | 將參照指定索引所指定方法原型的參照,移至指定的註冊器。 從 039版起,會出現在 Dex 檔案中。 | 
Packed-Switch-Payload 格式
| 名稱 | 格式 | 說明 | 
|---|---|---|
| ident | ushort = 0x0100 | 辨識虛擬指令 | 
| size | ushort | 資料表中的項目數 | 
| first_key | int | 第一個 (也是最低) 切換案例值 | 
| 目標 | int[] | size相對分支目標的清單。目標是相對於切換 Opcode 的位址,而非這個表格的位址。 | 
注意:這個資料表的執行個體程式碼單位總數為 (size * 2) + 4。
稀疏切換酬載格式
| 名稱 | 格式 | 說明 | 
|---|---|---|
| ident | ushort = 0x0200 | 辨識虛擬指令 | 
| size | ushort | 資料表中的項目數 | 
| 金鑰 | int[] | size鍵值清單,由低到高排序 | 
| 目標 | int[] | size相對分支目標清單,每個項目都對應至相同索引的鍵值。目標是相對於切換 Opcode 的位址,而非這個表格的位址。 | 
注意:這個資料表的執行個體程式碼單位總數為 (size * 4) + 2。
fill-array-data-payload 格式
| 名稱 | 格式 | 說明 | 
|---|---|---|
| ident | ushort = 0x0300 | 辨識虛擬指令 | 
| element_width | ushort | 每個元素的位元組數 | 
| size | uint | 資料表中的元素數 | 
| data | ubyte[] | 資料值 | 
注意:這個資料表的執行個體程式碼單位總數為 (size * element_width + 1) / 2 + 4。
數學運算詳細資料
注意:浮點運算必須遵循 IEEE 754 規則,使用四捨五入和漸進性下溢,除非另有說明。
| Opcode | C 語意 | 附註 | 
|---|---|---|
| neg-int | int32 a; int32 result = -a; | 一元二補法。 | 
| not-int | int32 a; int32 result = ~a; | 一元一補。 | 
| neg-long | int64 a; int64 result = -a; | 一元二補法。 | 
| not-long | int64 a; int64 result = ~a; | 一元一補。 | 
| neg-float | float a; float result = -a; | 浮點值否定。 | 
| neg-double | double a; double result = -a; | 浮點值否定。 | 
| int-to-long | int32 a; int64 result = (int64) a; | 將 int32的符號擴展至int64。 | 
| int 轉換為 float | int32 a; float result = (float) a; | 使用四捨五入法將 int32轉換為float。這會導致部分值的精確度降低。 | 
| int 轉換為 double | int32 a; double result = (double) a; | 將 int32轉換為double。 | 
| long-to-int | int64 a; int32 result = (int32) a; | 將 int64截斷為int32。 | 
| long-to-float | int64 a; float result = (float) a; | 使用四捨五入法將 int64轉換為float。這會導致部分值的精確度降低。 | 
| long-to-double | int64 a; double result = (double) a; | 使用四捨五入法將 int64轉換為double。這會導致部分值的精確度降低。 | 
| 浮點數轉整數 | float a; int32 result = (int32) a; | 使用捨入法將 float轉換為int32。NaN和-0.0(負零) 會轉換為整數0。無窮大和值的大小過大而無法表示時,會根據符號轉換為0x7fffffff或-0x80000000。 | 
| float-to-long | float a; int64 result = (int64) a; | 使用捨入法將 float轉換為int64。此處適用與float-to-int相同的特殊情況規則,但超出範圍的值會根據符號轉換為0x7fffffffffffffff或-0x8000000000000000。 | 
| 浮點轉換為雙精度 | float a; double result = (double) a; | 將 float轉換為double,並確切保留該值。 | 
| double-to-int | double a; int32 result = (int32) a; | 使用捨入法將 double轉換為int32。這裡適用的特殊案例規則與float-to-int相同。 | 
| double-to-long | double a; int64 result = (int64) a; | 使用捨入法將 double轉換為int64。這裡適用的特殊案例規則與float-to-long相同。 | 
| double-to-float | double a; float result = (float) a; | 使用四捨五入法將 double轉換為float。這會導致部分值的精確度降低。 | 
| int 到位元組 | int32 a; int32 result = (a << 24) >> 24; | 將 int32截斷為int8,延長結果的符號。 | 
| int 轉換為 char | int32 a; int32 result = a & 0xffff; | 將 int32截斷為uint16,但不延伸符號。 | 
| int-to-short | int32 a; int32 結果 = (a << 16) >> 16; | 將 int32截斷為int16,延長結果的符號。 | 
| add-int | int32 a, b; int32 result = a + b; | 二補加法。 | 
| 子 int | int32 a, b; int32 result = a - b; | 二補減法。 | 
| rsub-int | int32 a, b; int32 result = b - a; | 二補法反向減法。 | 
| mul-int | int32 a, b; int32 result = a * b; | 二補乘法。 | 
| div-int | int32 a, b; int32 result = a / b; | 二補法除法,四捨五入 (也就是截斷為整數)。如果 b == 0,則會擲回ArithmeticException。 | 
| rem-int | int32 a, b; int32 result = a % b; | 除法後的二補餘數。結果的符號與 a相同,更精確的定義為result == a - (a / b) * b。如果b == 0,則會擲回ArithmeticException。 | 
| and-int | int32 a, b; int32 result = a & b; | 位元 AND。 | 
| or-int | int32 a, b; int32 result = a | b; | 位元 OR。 | 
| xor-int | int32 a, b; int32 result = a ^ b; | 位元 XOR。 | 
| shl-int | int32 a, b; int32 result = a << (b & 0x1f); | 位元左移 (帶有遮罩引數)。 | 
| shr-int | int32 a, b; int32 result = a >> (b & 0x1f); | 以位元為單位向右移位 (含遮罩引數)。 | 
| ushr-int | uint32 a, b; int32 result = a >> (b & 0x1f); | 位元位移右 (含遮罩引數)。 | 
| add-long | int64 a, b; int64 result = a + b; | 二補加法。 | 
| 子長度 | int64 a, b; int64 result = a - b; | 二補減法。 | 
| mul-long | int64 a, b; int64 result = a * b; | 二補乘法。 | 
| div-long | int64 a, b; int64 result = a / b; | 二補法除法,四捨五入 (也就是截斷為整數)。如果 b == 0,則會擲回ArithmeticException。 | 
| rem-long | int64 a, b; int64 result = a % b; | 除法後的二補餘數。結果的符號與 a相同,更精確的定義為result == a - (a / b) * b。如果b == 0,則會擲回ArithmeticException。 | 
| and-long | int64 a, b; int64 result = a & b; | 位元 AND。 | 
| or-long | int64 a, b; int64 result = a | b; | 位元 OR。 | 
| xor-long | int64 a, b; int64 result = a ^ b; | 位元 XOR。 | 
| shl-long | int64 a; int32 b; int64 result = a << (b & 0x3f); | 位元左移 (帶有遮罩引數)。 | 
| shr-long | int64 a; int32 b; int64 result = a >> (b & 0x3f); | 位元有符號向右移位 (使用遮罩引數)。 | 
| ushr-long | uint64 a; int32 b; int64 result = a >> (b & 0x3f); | 位元位移右 (含遮罩引數)。 | 
| add-float | float a, b; float result = a + b; | 浮點加法。 | 
| 子浮動 | float a, b; float result = a - b; | 浮點數減法。 | 
| mul-float | float a, b; float result = a * b; | 浮點乘法。 | 
| div-float | float a, b; float result = a / b; | 浮點除法。 | 
| rem-float | float a, b; float result = a % b; | 除法後的浮點餘數。這個函式與 IEEE 754 餘數不同,並定義為 result == a - roundTowardZero(a / b) * b。 | 
| add-double | double a, b; double result = a + b; | 浮點加法。 | 
| 子雙精度浮點數 | double a, b; double result = a - b; | 浮點數減法。 | 
| mul-double | double a, b; double result = a * b; | 浮點乘法。 | 
| div-double | double a, b; double result = a / b; | 浮點除法。 | 
| rem-double | double a, b; double result = a % b; | 除法後的浮點餘數。這個函式與 IEEE 754 餘數不同,並定義為 result == a - roundTowardZero(a / b) * b。 | 
