深入理解java虚拟机 第八章 虚拟机字节码执行引擎

时间:2022-12-27 20:17:12

在不同的虚拟机实现里面,有可能是解释执行或编译执行

 

运行时栈帧结构

  栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,是虚拟机运行时数据区中的虚拟机栈的栈元素

  栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息

  每一个方法从调用开始至执行完成的过程,都对应一个栈帧在虚拟机栈里从入栈到出栈的过程

  一个线程中的方法调用链可能很长,很多方法都同时处于执行状态,只有位于栈顶的栈帧才是有效的,称为当前栈帧

  与这个栈帧相关联的方法称为当前方法

  局部变量表:

    局部变量表是一组变量值存储空间,由于存放方法参数和方法内部定义的局部变量

    在java程序编译为Class文件时,就在方法的Code属性中确定了该方法所需要分配的局部变量表的最大容量

    局部变量表的容量以变量槽为最小单位

    在方法执行时,虚拟机是使用局部变量表完成参数值到参数变量列表的传递过程

  操作数栈:

    操作数栈也称为操作栈,它是一个后入先出栈,

    当方法开始执行时,操作数栈为空,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容

  动态连接:

    每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态连接

  方法返回地址:

    两种退出方法的方式:

      1 执行引擎遇到任意一个方法返回的字节码指令,正常完成出口

      2 方法执行过程中出现异常,并且这个异常没有在方法体内得到处理,异常完成出口

  附加信息:

    

 

 

 

 

方法调用

  方法调用不等于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本

  解析:

    所有方法调用中的目标方法在Class文件里面都是一个常量池中的符号引用,

    在类加载的解析阶段,会将符号引用转化直接引用,前提是:方法在程序运行之前就有一个可确定的调用版本,

    并且在运行期是不可改变的

    在java语言中,符合“编译器可知,运行期不可变”这个要求的方法,主要包括静态方法和私有方法两大类

  分派:

    静态分派:

      依赖静态类型来定位方法执行版本的分派动作称为静态分派,典型应用是方法重载

    动态分派:

      在运行期根据实际类型确定方法执行版本的分派过程称为动态分派

  虚拟机动态分派的实现

    由于动态分派是非常频繁的动作,因此为类的方法区中建立一个虚方法表,

    虚方法表中存放着各个方法的实际入口地址,如果子类没有重写父类的方法,那么入口是一致的,

    如果子类重写了,那么子类方法表中的地址将会替换为指向子类实现版本的入口地址