从Constant Pool Java字节码访问值

时间:2016-01-06 15:09:21

标签: java constants bytecode operand

我有以下代码:

    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代替?

这个操作数是什么意思?

2 个答案:

答案 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