jvm字节码执行引擎

字节码执行引擎。
  
包含三部分:

字节码解释器
pc计数器
虚拟机栈 (栈帧结构 包括局部变量表 操作数栈 动态连接 返回地址。)
  
  
pc计数器:
pc计数器是通过字节码解释器根据代码逻辑 来选取下一条指令,并交给 pc计数器。可以理解就是解释器决定用来执行某个指令的 指令地址 。。 在一个方法内, 程序计数器记录的就是 当前正在执行的字节码指令地址。分支 循环 跳转 异常处理,线程切换后恢复到当前线程的正确执行位置 都是pc计数器的。
pc计数器是个概念模型。各种虚拟机会通过更高效的方式来实现。

  
  
方法执行和方法返回流程:

1.当调用invoke指令后,进入目标方法,会创建一个栈帧结构,并压入虚拟机栈。
2.此时调用者的pc计数器的值指会指向方法的返回地址,也就是方法返回后的下一条指令,该地址会保存在目标方法的栈帧中。
3.然后pc计数器会正常指向方法内部的指令 然后执行指令 指令完成后 并重新更新pc计数器。。
4.当遇到方法正常返回指令时,会把返回值压入调用者栈帧的操作数栈的中。或者使用两个栈帧的重叠区域。
5.把返回地址交给pc计数器 以执行下一条指令。

方法异常退出,返回地址是通过异常处理器来确定的。

  
  
操作数栈:

方法执行过程中,指令需要往该栈帧的操作数栈写入和提取内容来实现对数据的操作。
比如iadd指令 会把两个变量入栈,然后相加后出栈,再把结果入栈。

参数传递时候也是这样做的。一种方法是复制到被调用的栈帧的局部变量表中,另一种方法是采用重叠区域 让被调用者的操作数栈与调用者的局部变量表共享区域产生重叠,就能利用到调用者传递的参数。
  
  
方法的解析 :

解析是把一个把方法的符号引用变为直接引用的过程 是具体过程。

静态解析:
在编译期间就会确定,并在 类加载阶段就能执行将符号引用变为可确定的直接引用(编译期可知 运行期不可变的特性) 即方法的内存入口。符合条件的有静态方法和私有方法 实例构造器 父类方法 ,也就是invokestatic invokespecial 两个指令。
由于与类型直接关联和外部不可访问的特点决定 不可能通过动态分派也就是通过继承重写的方式存在多种版本。

动态解析:
也叫动态连接 就是编译期不可知 运行期 才决定直接引用。相对应的就是invokevirtual invokeinterface invokedynamic这三条指令。invokedynamic指令分派逻辑 不是jvm决定的。 而是用户所设定的引导方法决定的。还有个例外 final方法是非虚方法。调用的时候才会把类方法的符号引用解析到不同的直接引用上。

解析时机:
但是类加载的时候会提前对进行静态解析,但至于还解析什么虚拟机规范没有具体要求,只要求在操作符号引用的指令之前 要对符号引用完成解析就行。 那么动态解析肯定是 调用的时候才会解析。

  
  
方法的分派:
分派是描述的是根据jvm自身原理形成的多态机制,目的就是确定目标方法版本。
确定目标方法版本,有两种机制 方法重载 和方法重写,也就是所谓静态分派和动态分派。

静态分派:
静态类型决定了 方法重载。之所以叫静态,是因为重载是根据实参的 静态类型 而不是实际类型。方法重载在编译阶段就确定的。根实参的 实际类型没有关系。 sayHello(Human human)。 实参的静态类型匹配该形参。

动态分派,就是方法重写。是调用invokevirtual虚方法等方法。去常量池找到完整的符号引用,把类方法的符号引用解析到不同的直接引用上。所以说方法重写机制,要执行动态解析。 从而确定目标方法的位置。 实际类型是编译阶段不知道的。
  
  
单分派和多分派: 理论层面的东西。

确定目标方法 有两种宗量,一种参数不同 决定目标方法。叫重载机制。一种是方法接受者不同,而产生不同的目标方法是重写机制。

动态单分派:
动态分派是 动态单分派,意思是唯一影响虚拟机选择的因素只有此方法的接受者的实际类型作为依据。也就是说运行期间决定的 只有一种宗量。

静态多分派:
而编译期间,由于方法可以重载 参数不同 决定目标方法 是一种宗量 。而方法接受者不同,而产生不同的目标方法是另一个宗量 编译器选择是根据两种宗量 所以叫静态多分派。

  
  
动态类型语言: 类型检查的主体过程是在运行期还是在编译期。

java属于静态类型语言,因为一个对象调用方法的时候 完整的符号引用已经指明了该方法的类型。
动态类型语言,是指变量本身没有类型,值才有类型。 编译时最多只能确定方法名称 参数 返回值这些信息。而不会去确定方法所在的具体类型。

java1.7提供了两种方式来实现动态确定方法的接收者类型,一种是invoke包,一个事invokedynamic指令。

invoke包中的methodHandle 是一个方法引用,是为了动态确定目标方法。调用者与方法签名分离。其实就是类似反射。 只不过是对字节码层面的模拟调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值