Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the JVM have the iconst_2 - iconst_5 opcodes?

Tags:

java

jvm

opcodes

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?

like image 775
user1675642 Avatar asked Jun 09 '15 23:06

user1675642


People also ask

How many Java opcodes are there?

Java bytecode is the instruction set of the Java virtual machine. Each bytecode is composed of one, or in some cases two bytes that represent the instruction (opcode), along with zero or more bytes for passing parameters. Currently, in Jan 2017, there are 205 opcodes in use out of 256 possible byte-long opcodes.

What is an opcode in Java?

Each cell in the instruction format diagram represents a single 8-bit byte. The instruction's mnemonic is its name. Its opcode is its numeric representation and is given in both decimal and hexadecimal forms. Only the numeric representation is actually present in the Java Virtual Machine code in a class file.

What is LDC in Java?

It is Load Constant. It loads an item from the constant pool onto the stack.

How does bytecode work in Java?

How is Byte Code generated? Compiler converts the source code or the Java program into the Byte Code(or machine code), and secondly, the Interpreter executes the byte code on the system. The Interpreter can also be called JVM(Java Virtual Machine).


2 Answers

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.

like image 179
Tagir Valeev Avatar answered Sep 17 '22 18:09

Tagir Valeev


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

like image 28
Ankur Anand Avatar answered Sep 19 '22 18:09

Ankur Anand