目录
方法返回地址是什么?
存放调用该方法的PC寄存器的值
方法返回地址详解
正常情况下我们的程序方法结束有两种方式
- 方法正常结束
- 抛出异常
无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置,方法正常退出的时候,调用者的pc计数器的值作为返回地址,即调用该方法的指令的下一条指令的地址,而通过异常退出的,返回地址是要通过异常表来确定的,栈帧中一般不会保存这部分信息.因为在本质上,方法的退出就是当前栈帧出栈。此时,需要恢复上层方法的局部变量、操作数栈、设置PC寄存器值等,让调用者方法继续执行下去。所以在当前方法结束之后,我们需要将下一个指令作为方法返回地址返回给上一个调用者,让上一个调用者方法继续执行.
在方法执行的过程中遇到异常,并且这个异常没有在方法内进行处理,也就是只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,简称异常完成出口.方法执行过程中抛出异常时的异常处理,存储在一个异常处理表,方便发生异常的时候找到处理异常的代码
public class ReturnAddressTest2 {
public static void main(String[] args) {
try {
method();
} catch (ArithmeticException e) {
e.printStackTrace();
}
}
public static void method(){
int a = 1;
int b = 2;
int c = (a+b)/0;
}
}
经过反编译之后,程序抓取了异常之后,在当前方法对应的栈帧中的异常表中保存了一个异常信息
正常完成的出口和异常完成的出口区别在于:通过异常完成出口退出的不会给它的上层调用者产生任何的返回值。
方法返回地址的指令类型
一个方法在正常调用完成之后究竟需要使用哪一个返回指令还需要根据返回值的实际数据类型而定,在字节码指令中,返回指令包含ireturn(当返回值是boolean,byte,char,short,int类型的时候使用)lreturn,freturn,dreturn以及areturn,另外还有一个return指令共声明为void的方法,实例初始化方法,类和接口的初始化方法使用.
public class ReturnAddressTest {
public int returnInt(){return 0;} // ireturn
public boolean returnBoolean(){return false;} //ireturn
public float returnFloat(){return 0;} //freturn
public long returnLong(){return 0;} //lreturn
public Date returnDate(){return new Date();} //areturn
public byte returnByte(){return 0;} //ireturn
public short returnShort(){return 0;} //ireturn
public String returnString(){return "";} areturn
public void returnVoid(){} //return
}