从Instruction的角度来说,与return相关的opcode有6个,内容如下:
opcode | mnemonic symbol |
---|---|
172 | ireturn |
174 | freturn |
176 | areturn |
173 | lreturn |
175 | dreturn |
177 | return |
从ASM的角度来说,这些opcode是通过MethodVisitor.visitInsn(int opcode)方法来调用的。
return void type
从Java语言的视角,有一个HelloWorld类,代码如下:
public class HelloWorld {
public void test() {
// do nothing
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public void test();
Code:
0: return
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(RETURN);
methodVisitor.visitMaxs(0, 1);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: return // {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
... →
[empty]
The current method must have return type void.
- If no exception is thrown, any values on the operand stack of the current frame are discarded.
- The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
return primitive type
从Java语言的视角,有一个HelloWorld类,代码如下:
public class HelloWorld {
public int test() {
return 0;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public int test();
Code:
0: iconst_0
1: ireturn
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ICONST_0);
methodVisitor.visitInsn(IRETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: iconst_0 // {this} | {int}
0001: ireturn // {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
..., value →
[empty]
- The current method must have return type boolean, byte, short, char, or int. The value must be of type int.
- If no exception is thrown, value is popped from the operand stack of the current frame and pushed onto the operand stack of the frame of the invoker.
- Any other values on the operand stack of the current method are discarded.
The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
freturn
从Java语言的视角,有一个HelloWorld类,代码如下:
public class HelloWorld {
public float test() {
return 0;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public float test();
Code:
0: fconst_0
1: freturn
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(FCONST_0);
methodVisitor.visitInsn(FRETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: fconst_0 // {this} | {float}
0001: freturn // {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
..., value →
[empty]
- The current method must have return type float. The value must be of type float.
- If no exception is thrown, value is popped from the operand stack of the current frame. The value is pushed onto the operand stack of the frame of the invoker.
- Any other values on the operand stack of the current method are discarded.
The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
lreturn
这里需要注意的就是long类型在local variable和operand stack当中占用2个slot的位置。
从Java语言的视角,有一个HelloWorld类,代码如下:
public class HelloWorld {
public long test() {
return 0;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public long test();
Code:
0: lconst_0
1: lreturn
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(LCONST_0);
methodVisitor.visitInsn(LRETURN);
methodVisitor.visitMaxs(2, 1);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
..., value →
[empty]
- The current method must have return type long. The value must be of type long.
- If no exception is thrown, value is popped from the operand stack of the current frame and pushed onto the operand stack of the frame of the invoker.
- Any other values on the operand stack of the current method are discarded.
- The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
dreturn
从Java语言的视角,有一个HelloWorld类,代码如下:
public class HelloWorld {
public double test() {
return 0;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public double test();
Code:
0: dconst_0
1: dreturn
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(DCONST_0);
methodVisitor.visitInsn(DRETURN);
methodVisitor.visitMaxs(2, 1);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: dconst_0 // {this} | {double, top}
0001: dreturn // {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
..., value →
[empty]
- The current method must have return type double. The value must be of type double.
- If no exception is thrown, value is popped from the operand stack of the current frame. The value is pushed onto the operand stack of the frame of the invoker.
- Any other values on the operand stack of the current method are discarded.
- The interpreter then returns control to the invoker of the method, reinstating the frame of the invoker.
return reference type
从Java语言的视角,有一个HelloWorld类,代码如下:
public class HelloWorld {
public Object test() {
return null;
}
}
从Instruction的视角来看,方法体对应的内容如下:
$ javap -c sample.HelloWorld
Compiled from "HelloWorld.java"
public class sample.HelloWorld {
...
public java.lang.Object test();
Code:
0: aconst_null
1: areturn
}
从ASM的视角来看,方法体对应的内容如下:
methodVisitor.visitCode();
methodVisitor.visitInsn(ACONST_NULL);
methodVisitor.visitInsn(ARETURN);
methodVisitor.visitMaxs(1, 1);
methodVisitor.visitEnd();
从Frame的视角来看,local variable和operand stack的变化:
// {this} | {}
0000: aconst_null // {this} | {null}
0001: areturn // {} | {}
从JVM规范的角度来看,Operand Stack的变化如下:
..., objectref →
[empty]
- The objectref must be of type reference and must refer to an object of a type that is assignment compatible with the type represented by the return descriptor of the current method.
- If no exception is thrown, objectref is popped from the operand stack of the current frame and pushed onto the operand stack of the frame of the invoker.
- Any other values on the operand stack of the current method are discarded.
- The interpreter then reinstates the frame of the invoker and returns control to the invoker.