2

I have the following code:

    public static void f(){
        double i = 0.0;
        for(i = 0.0; i<100.0; i++){}   
    }

which translates to the following bytecode:

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

I'm confused about the line containing the comment //double 100.0d

I sort of understand what ldc2_w does. It grabs the appropriate constant from the constant pool. And the constant pool contains a list of defined constants after parsing the Java code, right?

But what is the purpose of #2? How would one know what number should go here? On an online tutorial I saw someone use #4 instead?

What does this operand mean?

Greg Peckory
  • 7,700
  • 21
  • 67
  • 114

2 Answers2

2

The #2 is an index in the constant pool for that constant, i.e. 2nd entry in the pool of constants. Note that constant pool has other entries, including method names, strings and so on.

Normally compiler translates java code into bytecode instructions and adds any required constant pool entries at the same time. See details for the constant pool data structures in JVM Specification. There are also bytecode manipulation frameworks like ASM and bytecode assemblers like Jasmin that completely abstracting the constant pool population from developer.

Eugene Kuleshov
  • 31,461
  • 5
  • 66
  • 67
  • But in this case there is only one constant, right? 100.0? So should the index not be `#1`? – Greg Peckory Jan 06 '16 at 15:38
  • i.e - what would `ldc2_w #1` return? – Greg Peckory Jan 06 '16 at 15:38
  • Updated my answer with some clarification, i.e. ldc2_w #1 may not be valid instruction if entry #1 is not a long constant. – Eugene Kuleshov Jan 06 '16 at 15:40
  • So say you had to write your own byte code, say in an exam situation, and you are given the above Java code. How would I know to write `ldc2_w #2` ? How would I look through all the entries in the constant pool to arrive at 2? – Greg Peckory Jan 06 '16 at 15:41
  • @Greg - Normally you wouldn't. Assemblers usually take care of that for you. If you're creating the entire classfile by hand, you'd create the constat pool too and hence know what is where. – Antimony Jan 06 '16 at 15:46
2

But what is the purpose of #2? How would one know what number should go here? On an online tutorial I saw someone use #4 instead?

Normally you don't. If you're writing bytecode assembly, you typically rely on the assembler to fill in the constant pool for you.

For example, if you write

ldc2_w 100.0

In Jasmin or Krakatau, the assembler will automatically create a constant pool entry for 100.0 and then fill in the appropriate index. It could be 2, it could be 4, it could be 50000. It depends on what else is in the constant pool, but you normally don't care about that.

The Krakatau assembler allows you to also specify constant pool entries manually. So if you wanted to make sure that your double was at position 2, you could do

.const [2] = Double 100.0
ldc2_w [2]

However, there is almost never any reason to do so. This is only useful if you care about the exact binary layout of the classfile.

As for why you're seeing the #2, that's because that's just the way Javap is. It's meant for a quick inspection of bytecode. If you use a different tool, you'll get different results. For example, the Krakatau disassembler would just print out ldc2_w 100.0 unless you specify roundtrip mode.

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • 1
    As a side note, I’d prefer `bipush 100; i2d` here. These two instructions take three bytes, just like the single `ldc2_w` instruction, but don’t need a constant pool entry (which takes nine bytes for a `double`). For the runtime performance, it’s unlikely to see a difference. – Holger Jan 06 '16 at 19:22