Why does the JVM have the iconst_2 - iconst_5 opcodes?

2.1k views Asked by At

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?

2

There are 2 answers

0
Tagir Valeev On BEST ANSWER

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.

0
Ankur Anand On

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