在java类文件中找到未指定的jvm字节码(0xe2)

2lpgd968  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(337)

我最近正在开发一个可以分析java类文件的程序。运行程序后,这是它的输出:


class test_1 {

    public static String a = "Hello World";

    public static void main(String[] args) {
        int j = 0;
        for(int i = 0;i<10;i++) {
            System.out.println(a);
            j = j + j*j +j/(j+1);
        }
    }
}

我得到了一个字节码0xe2,它没有在jvm规范14中指定。0xe2做什么??

lh80um4z

lh80um4z1#

您无法解释多字节操作码。从goto的参考中,格式为:

goto
branchbyte1
branchbyte2

无符号字节branchbyte1和branchbyte2用于构造有符号的16位branchhoffset,其中branchhoffset是(branchbyte1<<8)| branchbyte2。从这个goto指令的操作码地址的偏移量开始执行。目标地址必须是包含此goto指令的方法中指令的操作码的地址。 goto 是0xa7,后面应该跟2个字节,表示分支位置,使指令宽3个字节。您的代码忽略了这一点,反汇编1个字节,然后将接下来的2个字节视为有效指令,而它们不是。

iih3973s

iih3973s2#

你的程序输出每个字节就像它们是字节码指令一样,忽略了很多指令都有参数的事实,所以它们是多字节指令。
e、 g.程序错误地输出构造函数,如下所示:

2a: aload_0
b7: invokespecial
00: nop
01: aconst_null
b1: return

如果你跑了 javap -c test_1.class 但是,您将看到:

0: aload_0
1: invokespecial #1   // Method java/lang/Object."<init>":()V
4: return

冒号前的数字是偏移量,而不是字节码。如您所见,偏移量2和3丢失,因为 invokespecial 指令使用2个字节作为参数,记录如下:
格式

invokespecial
indexbyte1
indexbyte2

描述
未签名的 indexbyte1 以及 indexbyte2 用于将索引构造到当前类的运行时常量池中(§2.6),其中索引值为 (indexbyte1 << 8) | indexbyte2 .
2个字节 00 以及 01 ,索引为1,因此字节码指令如下 javap 显示: invokespecial #1 如果再看看常量池输出,就会发现常量#1是一个 methodrefObject 没有arg构造函数。
你的具体问题与字节码有关 a7 ff e2 ,它不是3条指令,而是 goto :
格式

goto
branchbyte1
branchbyte2

描述
无符号字节 branchbyte1 以及 branchbyte2 用于构造有符号的16位branchoffset,其中branchoffset是 (branchbyte1 << 8) | branchbyte2 .
意思是 ff e2branchoffset = 0xffe2 = -30 ,这意味着

a7: goto
ff: impdep2
e2: (null)

您的程序应该打印如下内容:

a7 ff e2: goto -30

相关问题