概览
从 Instruction 的角度来说,与 return 相关的 opcode 有 6 个,内容如下:
opcode | mnemonic symbol | opcode | mnemonic symbol | 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
ireturn
从 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
, orint
. Thevalue
must be of typeint
. - 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
. Thevalue
must be of typefloat
. - 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 的变化:
// {this} | {}
0000: lconst_0 // {this} | {long, top}
0001: lreturn // {} | {}
从 JVM 规范的角度来看,Operand Stack 的变化如下:
..., value →
[empty]
- The current method must have return type
long
. Thevalue
must be of typelong
. - 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
. Thevalue
must be of typedouble
. - If no exception is thrown,
value
is popped from the operand stack of the current frame. Thevalue
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 typereference
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.