字节码执行引擎知识点总结

◇◆丶佛笑我妖孽 提交于 2020-03-02 22:38:24

以下是在学习了《深入理解JVM》之后的对知识点的总结,其中对方法调用那一章做了大量实践和分析。


解释型还是编译型

  • 字节码的执行有解释型和编译型,根据具体情况才能说明java到底是什么执行方式。

基于栈还是基于寄存器

  • 虚拟机是基于栈的指令集,栈指的是java虚拟机栈,指令集指的字节码指令。

字节码指令在哪儿

  • 执行的字节码指令存放在字节码文件里的方法表里的code属性中。

java虚拟机栈与栈帧的关系

  • 虚拟机栈的基本单位为栈帧,栈帧之间的排列是先进后出。每个栈帧包括了局部变量表,操作数栈,动态连接,方法返回地址以及其他一些信息。
  • 每个栈帧的大小在编译期已经决定,因此栈帧中的每个结构都在编译期确定。
  • 虚拟机栈是线程私有,线程结束栈帧的所有内存都会清除。

局部变量表

  • 局部变量表的单位为slot。

  • 一个slot的大小必须要装的下除long,double类型之外其他基本类型,一般4个字节,也就是32位。

  • 对于long,double类型使用两个slot存放。

  • 局部变量表利用索引来获取值,就如同数组一样。局部变量表存放了方法的参数,以及方法中定义的所有变量。

  • 如果是实例方法,局部变量表第0个索引为this指针,其它变量从1开始索引。如果是类方法,没有this指针,其它变量直接从0开始索引。

  • 局部变量表的大小在编译期就已经决定,并存放于字节码文件中的方法表的max_locals字段中。

操作数栈

  • 操作数栈是一种先进后出的栈结构,是字节码执行过程中数据交互的场所。

动态连接

  • 动态连接指向常量池中的一个方法符号引用。
  • 与方法的动态连接有关。

方法返回地址

  • 一个方法没有出现异常,或者异常被捕捉为正常退出,有返回值。否则,为不正常退出,没有返回值。不管正不正常都会返回上一次调用地址。

栈帧与方法的关系

  • 当一个方法执行之后,会在线程所对应的虚拟机栈空间分配一个栈帧,一个栈帧代表一个方法。
  • 方法完成后,栈帧出栈。

字节码指令中的四个方法调用指令

  • invokestatic,invokestatic指令调用的方法表示在类加载过程之后,通过解析过程就已经确定。这些方法包括静态方法,实例构造器,私有方法和类方法四种。
  • 解析过程就是将符号引用替换为直接引用。
  • invokevirtual为虚方法指令。
  • invokeinterface为接口方法指令。

invokevirtual指令解析过程

  • 针对的是所调用方法的对象,而非方法的参数。
  • 具体过程如下:
  1. 找到操作数栈栈顶所指对象的实际类型。
  2. 如果此类型重写了方法,那么进行校验并执行,否则抛出异常
  3. 如果没有重写,继续寻找父类或接口。
  4. 始终没有找到抛出异常。

静态分派,重载,编译期确定

  • 重载是多态的体现,但是重载并不是在程序运行过程中动态绑定,虽然调用重载方法使用了invokevirtual,但是invokevitual的功能对重载并没有影响。
  • 重载在编译期通过参数的静态类型来决定调用那个方法。
  • 重载是的选择并不是唯一的,而是最适合的。

动态分派,重写,运行时确定

  • 动态分派是多态的体现,与重载不同,并不能在编译期确定。
  • 在字节码指令里,调用重写的方法,根据invokevitual的解析流程,会判断调用对象的实际类型,通过实际类型来选择调用哪个方法。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!