我最近在开发一个库时,在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
?弃用?他们是否有优势于他们记录的同行?
任何有识之士将不胜感激。