我有以下代码:
public static void f(){
double i = 0.0;
for(i = 0.0; i<100.0; i++){}
}
转换为以下字节码:
public static void f();
Code:
0: dconst_0
1: dstore_0
2: dconst_0
3: dstore_0
4: dload_0
5: ldc2_w #2 // double 100.0d
8: dcmpg
9: ifge 19
12: dload_0
13: dconst_1
14: dadd
15: dstore_0
16: goto 4
19: return
我对包含评论//double 100.0d
我理解ldc2_w
的作用。它从常量池中获取适当的常量。并且常量池在解析Java代码后包含已定义常量的列表,对吗?
但是#2
的目的是什么?怎么会知道应该去哪个号码?在在线教程中,我看到有人使用#4
代替?
这个操作数是什么意思?
答案 0 :(得分:2)
#2
是该常量的常量池中的索引,即常量池中的第二个条目。请注意,常量池有其他条目,包括方法名称,字符串等。
通常,编译器会将java代码转换为字节码指令,并同时添加任何所需的常量池条目。请参阅JVM Specification中有关常量池数据结构的详细信息。还有像ASM这样的字节码处理框架和像Jasmin这样的字节码汇编程序,它们完全抽象了开发人员的常量池数。
答案 1 :(得分:2)
但#2的目的是什么?怎么会知道应该是什么数字 到这里?在在线教程中我看到有人用#4代替?
通常你没有。如果您正在编写字节码汇编,则通常依赖汇编程序为您填写常量池。
例如,如果你写
ldc2_w 100.0
在Jasmin或Krakatau中,汇编程序将自动为100.0创建一个常量池条目,然后填入适当的索引。它可能是2,它可能是4,它可能是50000.这取决于常量池中的其他内容,但您通常不关心它。
Krakatau汇编程序允许您手动指定常量池条目。因此,如果你想确保双人位于第2位,你可以做到
.const [2] = Double 100.0
ldc2_w [2]
然而,几乎没有任何理由这样做。这仅在您关心类文件的确切二进制布局时才有用。
至于为什么你会看到#2,那是因为那就是Javap的方式。它用于快速检查字节码。如果您使用其他工具,您将获得不同的结果。例如,除非您指定往返模式,否则Krakatau反汇编程序只会打印ldc2_w 100.0
。