Reputation: 1642
I was testing with ASM framework, and I barely can't understand why this fragment of code produce the int value 10
.
For more details: the method returns an int and I printed the int back.
// This is the complete ASM visit of this method
// ...
MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, method.getName(), Type.getMethodDescriptor(method), null, null);
mv.visitCode();
mv.visitIntInsn(Opcodes.BIPUSH, 0);
mv.visitIntInsn(Opcodes.BIPUSH , 0);
mv.visitIntInsn(Opcodes.ISTORE, 2);
mv.visitIntInsn(Opcodes.ILOAD, 1);
mv.visitInsn(Opcodes.IRETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
// ...
The decompiler show even some weird code. Decompiler output:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
public class HelloWorld implements Add {
public HelloWorld() {
}
public int add(int var1, int var2) {
boolean var3 = false;
return var1;
}
}
Why does the function returns 10
? Is it a bug ? Does this invoke a sort of "undefined behaviour", because variables are loaded into "self" because pushed back?
How does JVM handle the variables and how to allocate it, is it stack based ? If so, then the aload
will just push duplicate value of data
stack before aload: var1 var2 var3
stack after aload_1: var1 var2 var3 var1
Or am I totally wrong? It looks like a bit overworks instead of using registries.
Upvotes: 0
Views: 202
Reputation: 67377
Who wrote that byte code? What is it supposed to do? What it actually does is:
(byte) 0
onto operand stack as an integer(byte) 0
onto operand stack one more time0
from stack and store as integer in local variable table, slot #2You also need to know that in the local variable table
this
for the called method, i.e. a reference to the HelloWorld
instance,var1
,var2
.So if the method returns 10, it means that you must have called the method with a var1
value of 10 because you return the content of slot #1 unchanged. There is no clue that you add anything here like the method name implies. What it does instead is push 2x 0
onto the stack, but only using one of them, overwriting var2
for whatever reason before returning var1
, as I said. The decompiler then tries to make sense of it, doing a pretty good job.
Update: If you want to implement this
public int add(int var1, int var2) {
return var1 + var2;
}
then your byte code ought to be like this:
ILOAD 1
ILOAD 2
IADD
IRETURN
Upvotes: 2