私は最近、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 でページを次々と探し回った後、このドキュメントLDC*_QUICK
でオペコードについての言及を見つけました。
LDC_QUICK
オペコードでそれから引用します:
操作定数プールから項目をプッシュ
フォーム ldc_quick = 203 (0xcb)
積み上げ……、アイテム
説明インデックスは、現在のクラス (§3.6) の定数プールへの有効なインデックスでなければならない符号なしバイトです。index の定数プール項目は既に解決されている必要があり、1 ワード幅でなければなりません。アイテムは定数プールからフェッチされ、オペランド スタックにプッシュされます。
注この命令のオペコードはもともと ldc でした。ldc 命令のオペランドは変更されません。
大丈夫。面白そうだったので、やってみることにしました。LDC_QUICK
と同じ形式のように見えるので、オペコードをLDC
に変更しました。これは失敗に終わりましたが、JVM は明らかにそれを認識していました。変更されたファイルを実行しようとした後、JVM は次の出力でクラッシュしました。LDC
LDC_QUICK
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
sを受け取っているのはなぜですか? 非推奨?そして、彼らは文書化された対応物よりも利点がありますか?
どんな洞察も大歓迎です。