已知
- 程序计数器是线程私有的,记录下一条要执行的指令地址。
- 当有方法被调用时,对应的栈帧会入栈形成新的栈顶帧。
- return返回指定的数据
疑惑
当前栈顶的栈帧被弹出后,第二个栈帧变为栈顶栈帧。由于程序计数器是线程私有,那JVM怎么知道下一条要执行的指令地址的?是在每个栈帧中都记录调用方法时的地址值吗?
形象点说就是,先执行A方法,在A方法中调用B方法,B方法执行完毕返回到A方法,此时JVM怎么知道该从哪一条语句开始执行?程序寄存器是跟着方法更新的,也就说到B方法里后,程序寄存器就丢失了A方法的执行条数,再返回A方法,程序寄存器应该不知道执行到哪里了才对。
猜测
应该每个栈帧中,都是有个地方存储了这个值(即B方法栈帧中存储了A方法的执行条数),方法结束后返回这个值,这样才能更新程序计数器执行下一步操作。
我想问的是
我的理解对吗?是这样操作的吗?
如果是是存在哪里呢?操作数栈?是通过return指令返回的吗?
如果不是又是怎么操作的呢?
求各位指点指点!
方法返回地址
当一个方法开始执行后,只有两种方式可以退出这个方法。第一种方式是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者(调用当前方法的方法称为调用者),是否有返回值和返回值的类型将根据遇到何种方法返回指令来决定,这种退出方法的方式称为正常完成出口(Normal Method Invocation Completion)。
另外一种退出方式是,在方法执行过程中遇到了异常,并且这个异常没有在方法体内得到处理,无论是Java虚拟机内部产生的异常,还是代码中使用athrow字节码指令产生的异常,只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种退出方法的方式称为异常完成出口(Abrupt Method Invocation Completion)。一个方法使用异常完成出口的方式退出,是不会给它的上层调用者产生任何返回值的。
无论采用何种退出方式,在方法退出之后,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态。一般来说,方法正常退出时,调用者的PC计数器的值可以作为返回地址,栈帧中很可能会保存这个计数器值。而方法异常退出时,返回地址是要通过异常处理器表来确定的,栈帧中一般不会保存这部分信息。
方法退出的过程实际上就等同于把当前栈帧出栈,因此退出时可能执行的操作有:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令等。
出自《深入理解java虚拟机》