8

While reading the JVM specification (as one does), I was very surprised when I came across the 7 iconst_<i> opcodes. After all, there is only one byte to play with.

I very rarely write the literals for 2, 3, 4 or 5 in my code. I can understand why -1, 0 and 1 might be treated specially, but it seems amazing to me that the designers would want to blow 4 precious opcodes on numbers that just happen to be quite small.

Does anyone know if there's a good reason for this? Am I underestimating the benefit of these?

Steve Lillis
  • 3,263
  • 5
  • 22
  • 41
user1675642
  • 747
  • 2
  • 5
  • 15
  • There are 255 op codes available. It's quite hard to use anywhere near all of them when designing a VM instruction set. Obviously Jim Gosling thought it was a good dea, and it's cost-free until you run out, like giving away free theatre tickets, so why not? – user207421 Jun 09 '15 at 23:40

2 Answers2

7

I think, your assumption is correct: just to make the bytecode smaller and Java interpreter a tiny bit faster (there were no JIT compiler those times). Note that these bytecodes may be used much more often than you expect. For example, consider the following code:

int[] a = {10, 20, 30, 40};

Effectively it's compiled to something like:

int[] a = new int[4];
a[0] = 10;
a[1] = 20;
a[2] = 30;
a[3] = 40;

So here iconst_0 to iconst_4 are used even though you have no such constants in the source code.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
5

Hope this can Clarify your Question Why waste the 4 Opcode ..

See the Byte Code of this code

public static void main(String[] args) {
        int b = 20;
        int c = 5;
        int d= 6;
    }

part of Byte Code

0: bipush        20
 2: istore_1
 3: iconst_5
 4: istore_2
 5: bipush        6
 7: istore_3

As you can see for number greater 5 it's starts using bipushwhich are typically less efficient than the equivalent iconst_<n> and also take up more bytes in the class file.

bipush byte1 expands byte1 to an int and then pushes it onto the stack, because every slot on the Java stack is 32 bits wide (JVM is Stack Based Virtual Machines)

And to see if bipush takes up more byte ..

See the class file size of two following code.(This size are on my 64bit machine.. it may differ on your machine but the difference will be same)

public class Test2 {

    public static void main(String[] args) {
        int b = 5;

    }

}

size 406 bytes

now if i replace b =6 ; the size of the same class file becomes 407 bytes which remains constant till even when b=127 which also uses bipush. This difference in Size is due to the fact that bipush has 2 bytes, one byte opcode, second byte immediate constat value

bipush format:

bipush
byte

as you can see from the line 5: bipush 6 in bytecode while iconst_<n> uses 1 byte only.

So such bytecodes are defined for some commonly pushed numbers, to increase the efficiency of bytecode execution and reduce the size of bytecode streams.

and as Tagir said those numbers would be used more often than you would think

Ankur Anand
  • 3,873
  • 2
  • 23
  • 44