我最近正在开发一个可以分析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);
}
}
}我得到了一个没有在jvm规范14中指定的字节码0xe2。0xe2做什么??
发布于 2021-01-01 16:17:35
你的程序输出每一个字节,如果它们是字节码指令,忽略了许多指令都有参数的事实,所以它们是多字节指令。
例如,您的程序错误地输出构造函数如下:
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个字节,这在文档中有如下说明:
格式 专用indexbyte1 indexbyte2 Description 未签名的
indexbyte1和indexbyte2用于在当前类(§2.6)的运行时常量池(§2.6)中构造索引,其中索引的值为(indexbyte1 << 8) | indexbyte2。
当两个字节为00和01时,索引为1,因此字节码指令如javap所示:invokespecial #1
如果然后查看常量池输出,您将看到常量#1是methodref到Object的no-arg构造函数。
您的具体问题与字节码a7 ff e2有关,它不是3个指令,而是goto的3字节指令。
格式 goto branchbyte1 branchbyte2 Description 无符号字节
branchbyte1和branchbyte2用于构造带符号16位分支偏移量,其中分支偏移量为(branchbyte1 << 8) | branchbyte2。
意味着ff e2是branchoffset = 0xffe2 = -30,这意味着
a7: goto
ff: impdep2
e2: (null)你的程序应该打印这样的东西:
a7 ff e2: goto -30发布于 2021-01-01 15:38:26
无法解释多字节操作码。在后藤参考中,格式是:
goto
branchbyte1
branchbyte2无符号字节branchbyte1和branchbyte2用于构造带符号的16位分支偏移量,其中分支偏移量为(branchbyte1 << 8) _\_\从这个goto指令的操作码地址开始执行该偏移量。目标地址必须是包含此goto指令的方法中指令的操作码的地址。
goto是0xa 7,后面应该是两个字节,表示分支位置,使指令宽3个字节。您的代码忽略了这一点,将1字节解压缩,然后将接下来的2字节视为有效指令,而它们不是。
https://stackoverflow.com/questions/65530989
复制相似问题