美文网首页
jvm a方法调用另一个b方法 当b方法返回后 jvm是怎么知道

jvm a方法调用另一个b方法 当b方法返回后 jvm是怎么知道

作者: dozenx | 来源:发表于2018-10-17 09:37 被阅读24次

在最初接触jvm的几天里,我一直有这样的疑问,jvm a方法调用另一个b方法 当b方法返回后 jvm是怎么知道要返回到哪里的?
查阅了程序计数器的许多资料,都讲的不是很明白,对程序计数器都差不多是同样的描述文字.
后来在看到栈帧的介绍的时候突然看到了返回地址这么一个东西,感觉就和我的答案非常接近了,继续寻找答案的同时也顺便弄明白了程序计数器是怎么工作的.

每个线程有有许多栈帧,每个栈帧的结构如下图

栈帧结构图

image

方法返回地址

存放调用调用该方法的pc计数器的值。当一个方法开始之后,只有两种方式可以退出这个方法:1、执行引擎遇到任意一个方法返回的字节码指令,也就是所谓的正常完成出口。2、在方法执行的过程中遇到了异常,并且这个异常没有在方法内进行处理,也就是只要在本方法的异常表中没有搜索到匹配的异常处理器,就会导致方法退出,这种方式成为异常完成出口。正常完成出口和异常完成出口的区别在于:通过异常完成出口退出的不会给他的上层调用者产生任何的返回值。
无论通过哪种方式退出,在方法退出后都返回到该方法被调用的位置,方法正常退出时,调用者的pc计数器的值作为返回地址,而通过异常退出的,返回地址是要通过异常处理器表来确定,栈帧中一般不会保存这部分信息。本质上,方法的退出就是当前栈帧出栈的过程。

也就是说每个线程都有一个程序计数器,当从a方法到b方法的时候,会产生一个新的栈帧,会将当前方法块内的执行位置(也就是程序计数器的值)存入到这个新的栈帧的返回地址内

代码

package com;

public class test2 {

    public static void main(String args[]) {
        int a = 1;
        int b = a + 1;
        test2 c = new test2();
        int d = c.method1(a);
    }

    public int method1(int v1) {
        v1 = v1 + 1;
        v1 = method2(v1);
        return v1;
    }

    public int method2(int v2) {
        v2 = v2 + 1;
        return v2;
    }

}

反编译结果

G:\>javap -c test2.class
Compiled from "test2.java"
public class test2 {
  public test2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_1
       1: istore_1
       2: iload_1
       3: iconst_1
       4: iadd
       5: istore_2
       6: new           #2                  // class test2
       9: dup
      10: invokespecial #3                  // Method "<init>":()V
      13: astore_3
      14: aload_3
      15: iload_1
      16: invokevirtual #4                  // Method method1:(I)I
      19: istore        4
      21: return

  public int method1(int);
    Code:
       0: iload_1
       1: iconst_1
       2: iadd
       3: istore_1
       4: aload_0
       5: iload_1
       6: invokevirtual #5                  // Method method2:(I)I
       9: istore_1
      10: iload_1
      11: ireturn

  public int method2(int);
    Code:
       0: iload_1
       1: iconst_1
       2: iadd
       3: istore_1
       4: iload_1
       5: ireturn
}

主要参考

https://blog.csdn.net/dd864140130/article/details/49515403#commentBox

看过的文章:

https://www.cnblogs.com/dolphin0520/p/3613043.html

https://www.2cto.com/kf/201712/704110.html

相关文章

  • jvm a方法调用另一个b方法 当b方法返回后 jvm是怎么知道

    在最初接触jvm的几天里,我一直有这样的疑问,jvm a方法调用另一个b方法 当b方法返回后 jvm是怎么知道要返...

  • JVM(二)

    本地方法栈 本地方法栈保存的是 native 方法的信息。 当一个 JVM 创建的线程调用 native 方法后,...

  • JVM学习笔记之栈区

    JVM学习笔记之栈区 本文主要内容: 栈是什么?栈帧又是什么?在JVM中,main方法调用say方法后,是怎么运行...

  • JVM系列之 _call_stub_entry初始化

    在上文JVM系列之函数调用入门已经简单介绍了JVM是如何调用方法的:JVM先调用call_stub()方法将_ca...

  • JVM--方法调用

    方法调用不是方法执行,方法调用是让jvm确定调用哪个方法,所以,程序运行时的它是最普遍、最频繁的操作。jvm需要在...

  • main

    main方法 main 方法是由jvm调用的,jvm也是一个程序 public :保证在任何情况下,jvm都对其方...

  • Stack栈

    先进后出 DEBUG时,会有栈的信息 A方法调用B方法,B方法调用C方法;A在栈底,上一层是B,再上一层是C,执行...

  • Java基础-6 main方法

    main方法是由jvm调用的,jvm也是一个程序。 main方法详解: 没有static修饰的后果:1. java...

  • swift中的方法嵌套

    在方法A中可以定义方法B,并在方法A中调用方法B。

  • JVM方法调用

    JVM方法调用 背景 Java文件在编译过程中不会进行传统编译的连接步骤,方法调用的目标方法以符号引用的方式存储在...

网友评论

      本文标题:jvm a方法调用另一个b方法 当b方法返回后 jvm是怎么知道

      本文链接:https://www.haomeiwen.com/subject/rdddaftx.html