我最近正在开发一个可以分析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做什么??
2条答案
按热度按时间lh80um4z1#
您无法解释多字节操作码。从goto的参考中,格式为:
无符号字节branchbyte1和branchbyte2用于构造有符号的16位branchhoffset,其中branchhoffset是(branchbyte1<<8)| branchbyte2。从这个goto指令的操作码地址的偏移量开始执行。目标地址必须是包含此goto指令的方法中指令的操作码的地址。
goto
是0xa7,后面应该跟2个字节,表示分支位置,使指令宽3个字节。您的代码忽略了这一点,反汇编1个字节,然后将接下来的2个字节视为有效指令,而它们不是。iih3973s2#
你的程序输出每个字节就像它们是字节码指令一样,忽略了很多指令都有参数的事实,所以它们是多字节指令。
e、 g.程序错误地输出构造函数,如下所示:
如果你跑了
javap -c test_1.class
但是,您将看到:冒号前的数字是偏移量,而不是字节码。如您所见,偏移量2和3丢失,因为
invokespecial
指令使用2个字节作为参数,记录如下:格式
描述
未签名的
indexbyte1
以及indexbyte2
用于将索引构造到当前类的运行时常量池中(§2.6),其中索引值为(indexbyte1 << 8) | indexbyte2
.2个字节
00
以及01
,索引为1,因此字节码指令如下javap
显示:invokespecial #1
如果再看看常量池输出,就会发现常量#1是一个methodref
到Object
没有arg构造函数。你的具体问题与字节码有关
a7 ff e2
,它不是3条指令,而是goto
:格式
描述
无符号字节
branchbyte1
以及branchbyte2
用于构造有符号的16位branchoffset,其中branchoffset是(branchbyte1 << 8) | branchbyte2
.意思是
ff e2
是branchoffset = 0xffe2 = -30
,这意味着您的程序应该打印如下内容: