我最近在開發一個庫時,在JVM字節碼上執行操作的庫上沒有任何文檔(我已經找到),但是JVM參考實現可以識別這些操作碼。我發現這些名單,他們是:JVM中的非法操作碼
BREAKPOINT = 202;
LDC_QUICK = 203;
LDC_W_QUICK = 204;
LDC2_W_QUICK = 205;
GETFIELD_QUICK = 206;
PUTFIELD_QUICK = 207;
GETFIELD2_QUICK = 208;
PUTFIELD2_QUICK = 209;
GETSTATIC_QUICK = 210;
PUTSTATIC_QUICK = 211;
GETSTATIC2_QUICK = 212;
PUTSTATIC2_QUICK = 213;
INVOKEVIRTUAL_QUICK = 214;
INVOKENONVIRTUAL_QUICK = 215;
INVOKESUPER_QUICK = 216;
INVOKESTATIC_QUICK = 217;
INVOKEINTERFACE_QUICK = 218;
INVOKEVIRTUALOBJECT_QUICK = 219;
NEW_QUICK = 221;
ANEWARRAY_QUICK = 222;
MULTIANEWARRAY_QUICK = 223;
CHECKCAST_QUICK = 224;
INSTANCEOF_QUICK = 225;
INVOKEVIRTUAL_QUICK_W = 226;
GETFIELD_QUICK_W = 227;
PUTFIELD_QUICK_W = 228;
IMPDEP1 = 254;
IMPDEP2 = 255;
他們似乎是爲他們的其他實現替代,但有不同的操作碼。經過Google長時間的翻頁後,我偶然發現this document中的LDC*_QUICK
操作碼。從它
報價在LDC_QUICK
操作碼:
操作推項目從常量池中
形式 ldc_quick = 203(0xcb)
堆棧 ... ...,項目
描述索引是一個無符號字節,必須是當前類的常量池(§3.6)中的有效索引。索引處的常量 池項目必須已經解析並且必須是一個字寬爲 。該項目從常量池中提取並推送到操作數堆棧中。
備註該指令的操作碼最初是ldc。 ldc指令的操作數未被修改。
好的。看起來有趣,所以我決定嘗試一下。 LDC_QUICK
似乎與LDC
的格式相同,因此我開始將LDC
操作碼更改爲LDC_QUICK
。這導致失敗,儘管JVM明顯地認識到了它。嘗試運行修改後的文件後,JVM與以下輸出一起崩潰:
Exception in thread "main" java.lang.VerifyError: Bad instruction: cc
Exception Details:
Location:
Test.main([Ljava/lang/String;)V @9: fast_bgetfield
Reason:
Error exists in the bytecode
Bytecode:
0000000: bb00 0559 b700 064c 2bcc 07b6 0008 572b
0000010: b200 09b6 000a 5710 0ab8 000b 08b8 000c
0000020: 8860 aa00 0000 0032 0000 0001 0000 0003
0000030: 0000 001a 0000 0022 0000 002a b200 0d12
0000040: 0eb6 000f b200 0d12 10b6 000f b200 0d12
0000050: 11b6 000f bb00 1259 2bb6 0013 b700 14b8
0000060: 0015 a700 104d 2cb6 0016 b200 0d12 17b6
0000070: 000f b1
Exception Handler Table:
bci [84, 98] => handler: 101
Stackmap Table:
append_frame(@60,Object[#41])
same_frame(@68)
same_frame(@76)
same_frame(@84)
same_locals_1_stack_item_frame(@101,Object[#42])
same_frame(@114)
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
at java.lang.Class.getMethod0(Unknown Source)
at java.lang.Class.getMethod(Unknown Source)
at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
上述錯誤提供了混合消息。很明顯,班級文件驗證失敗:java.lang.VerifyError: Bad instruction: cc
。同時,JVM識別操作碼:@9: fast_bgetfield
。此外,它似乎認爲這是一個不同的指令,因爲fast_bgetfield
並不意味着不斷推動...
我認爲它公平地說,我很困惑。這些非法操作碼是什麼? JVM是否運行它們?我爲什麼收到VerifyError
?棄用?他們是否有優勢於他們記錄的同行?
任何有識之士將不勝感激。