1.执行引擎

  • 所有Java虚拟机的执行引擎都是一致的: 输入的是字节码文件,处理过程就是解析过程,最后输出执行结果。
  • 在整个过程不同的数据在不同的结构中进行处理。

2.栈帧

  • jvm进行方法调用和方法执行的数据结构,是虚拟机栈的元素。
  • (图片来自网络)
  1. 栈帧包括:局部变量表、操作数栈、动态链接、方法返回地址等
  2. 编译期就确定了需要多大的局部变量表,多深的操作数栈,这些信息全在字节码中。
  3. 只有位于栈顶的栈帧才有效,称为当前栈帧,所对应的方法就是当前正在执行的方法。

2.1 局部变量表

  • 存放方法参数和方法内部定义的局部变量。
  1. 容量以变量槽slot为单位,slot内存大小随着需求而变化并且不固定。
  2. 方法执行时jvm使用局部变量表完成参数值到参数列表的传递过程。
  3. slot可以被其他变量复用。
  4. 局部变量不存在准备阶段,所以不会赋予系统初始值,如果不初始化那么他就不能使用。
  5. jvm通过索引定位的方式定位slot,从0到最大slot数量。0位索引slot是用来存放方法所属对象实例的引用(this),之后按参数列表分配slot,再后按照局部变量顺序分配slot。

2.2操作数栈

  • 方法刚刚开始执行时为空,在执行过程中会有各种字节码指令往操作数栈中写入和提取内容,也就是入栈/出栈操作。
  • 概念上两个栈帧相互独立,但大多数虚拟机会存在一些优化,让下面栈帧的操作数栈部分区域和上面栈帧的部分局部变量表重合,成为共享区域。

2.3动态链接

  • 保存 指向运行时常量池中 该栈帧所属方法的 引用。
  • 作用就是 运行期间将符号引用转化为直接引用。

2.4方法返回地址

  • 保留一些退出方法时 上层方法执行状态 的信息

3.方法的调用,动态绑定过程。

  • 编译过程不包括传统的连接,class文件中只是存符号引用,而不是直接引用。
  • 方法调用就是确定该方法是哪个类的哪个方法换个说法就是绑定,这不同于方法执行。
  1. 解析

    • 符号引用转化为直接引用,因为编译器并不知道分配内存后某个变量具体内存位置,所以编译时使用一个符号代替,分配内存后该变量所在的内存位置就等于这个符号,解析阶段找到这个符号对应的内存位置然后指向她,这就是符号引用转化为直接引用。
    1. 类加载的解析阶段会把 部分符号引用转化为直接引用,但这种解析的前提条件就是:方法在程序执行之前就有一个就可以确定的版本,并且在运行期间不可变。
    2. 编译期可知运行期不可变这种方法有static和private方法,想想也是,这两种方法只有定义他们的类才能调用,他们一出生就确定了唯一的主人。他们不可能被继承或者重写其他版本。
    3. 实例构造器,父类方法这2中也能确定唯一的版本,所以这些方法也是在类加载阶段解析为直接引用。
    4. 静态方法,私有方法,实例构造器,父类方法这些方法可确定唯一版本所以统称为 非虚方法,final方法也是非虚方法。
  2. 分派调用

    • 分派调用就是多态特征的体现,在重载重写的方法中正确确定版本。
    1. 静态类型和动态类型

      • Human man =  new  Man();
      • Human 就是变量man 的静态类型, Man 就是man 的实际类型。
      • 静态类型在编译期可知,动态类型在运行期才能确定
    2. 静态分派:根据参数的静态类型确定该方法使用的版本
      • 方法被重载了好几个版本,确定要使用哪一个版本就是通过当前调用方法传入参数的静态类型确定版本。
      • 静态分派会找到一个和参数静态类型最适合的版本,如 int 类型传入多个没有int的重载版本中还会找到float版本。
      • 静态分派在编译期确定调用哪一个版本,并把符号引用记录下来。
      • 注意静态分派只确定了方法的版本,如果一个类没有继承其他类当前方法也不是覆写了父类方法,那么他就只有这一个版本可用,如果重写了父类方法,那么就由动态分派来确定使用哪个重写方法。
    3. 动态分派:运行期间根据调用方法的对象的实际类型确定使用哪个类的方法,也就是确定使用哪个重写方法。编译期间无法确定实际类型
      1. 找到调用当前方法的对象的实际类型
      2. 在实际类型中由静态分派确定方法版本。
      3. 如果找到对应版本则检查访问权限如果通过则返回此方法的引用。
      4. 如果找不到则从下往上在父类中找,如果找不到则抛出异常。
    4. 单分派多分派
      • 方法的接收者和参数统称为综量
      • 静态分派是根据方法参数确定的,方法参数可以有多个所以是多个宗量,属于多分派。
      • 动态分派是根据一个实际类型确定的所以属于单宗量,所以是单分派。
      • Java 目前是一门静态多分派,动态单分派的语言。
    5. 静态分派和动态分派的区别
      1. 静态分派通过参数类型查找重载版本,并且是参数的静态类型。
      2. 动态分派通过调用方法的对象查找重写版本,并且是对象的实际类型。

4. 字段的调用和方法的调用不同

  1.  当一个引用变量它的编译时的类型和运行是的类型不一样时:

    • 通过引用调用字段则调用的是 编译时类型(静态类型 )对象的字段,也就是父类的字段。
    • 通过引用调用方法则是通过动态分派调用实际类型的方法,如果没有就去父类中查找。

JVM字节码执行引擎和动态绑定原理的更多相关文章

  1. JVM总结(五):JVM字节码执行引擎

    JVM字节码执行引擎 运行时栈帧结构 局部变量表 操作数栈 动态连接 方法返回地址 附加信息 方法调用 解析 分派 –“重载”和“重写”的实现 静态分派 动态分派 单分派和多分派 JVM动态分派的实现 ...

  2. 一夜搞懂 | JVM 字节码执行引擎

    前言 本文已经收录到我的 Github 个人博客,欢迎大佬们光临寒舍: 我的 GIthub 博客 学习导图 一.为什么要学习字节码执行引擎? 代码编译的结果从本地机器码转变为字节码,是存储格式发展的一 ...

  3. 深入理解JVM—字节码执行引擎

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220122204355694/ 前面我们不止一次的提到,Java是一种跨平台的语言,为 ...

  4. JVM字节码执行引擎

    一.概述 在不同的虚拟机实现里面,执行引擎在执行Java代码的时候可能会有解释执行(通过解释器执行)和编译器执行(通过即时编译器产生本地代码执行)两种选择,所有的Java虚拟机的执行引擎都是一致的:输 ...

  5. 图解JVM字节码执行引擎之栈帧结构

    一.执行引擎      “虚拟机”的概念是相对于“物理机”而言的,这两种“机器”都有执行代码的能力.物理机的执行引擎是直接建立在硬件处理器.物理寄存器.指令集和操作系统层面的:而“虚拟机”的执行引擎是 ...

  6. 深入理解JVM虚拟机5:虚拟机字节码执行引擎

    虚拟机字节码执行引擎   转自https://juejin.im/post/5abc97ff518825556a727e66 所谓的「虚拟机字节码执行引擎」其实就是 JVM 根据 Class 文件中给 ...

  7. JVM学习笔记:字节码执行引擎

    JVM学习笔记:字节码执行引擎 移步大神贴:http://rednaxelafx.iteye.com/blog/492667  

  8. JVM基础结构与字节码执行引擎

    JVM基础结构 JVM内部结构如下:栈.堆. 栈 JVM中的栈主要是指线程里面的栈,里面有方法栈.native方法栈.PC寄存器等等:每个方法栈是由栈帧组成的:每个栈帧是由局部变量表.操作数栈等组成. ...

  9. 深入理解Java虚拟机(类文件结构+类加载机制+字节码执行引擎)

    目录 1.类文件结构 1.1 Class类文件结构 1.2 魔数与Class文件的版本 1.3 常量池 1.4 访问标志 1.5 类索引.父索引与接口索引集合 1.6 字段表集合 1.7 方法集合 1 ...

随机推荐

  1. ES6装饰器Decorator基本用法

    1. 基本形式 @decorator class A {} // 等同于 class A {} A = decorator(A); 装饰器在javascript中仅仅可以修饰类和属性,不能修饰函数.装 ...

  2. oracle-java7-installer安装java失败之后的处理

    最开始尝试使用installer安装jdk7,但是未能进行完整,之后每次安装软件都会报错,说oracle-java7-installer处有错误,查得如下解决办法: sudo rm /var/lib/ ...

  3. 【套题】qbxt国庆刷题班D2

    D2 今天的题感觉还是好妙的 T1 传送门 Description 现在有一张\(n\)个节点\(m\)条边的无向连通图\(G=(V,E)\),满足这张图中不存在长度大于等于3的环且图中没有重边和自环 ...

  4. Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017 - Final Round Div. 2 Edition)A 水 B 二分 C并查集

    A. Petr and a calendar time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

  5. ubuntu下安装golang

    1.安装 sudo apt-get install golang 2.查看go的安装路径 go env 查看 GOROOT="/usr/lib/go-1.6" 3.修改环境变量 e ...

  6. java后台svg转成png

    1.替换img地址 /** * 替换img地址 * @param str -- 前台svg字符串 * @return */ private String transferImgPath(HttpSer ...

  7. SpringMVC 用注解Annotation驱动的IoC功能@Autowired @Component

    转载自:http://blog.csdn.net/lufeng20/article/details/7598564 本文分为三个部分:概述.使用注解进行属性注入.使用注解进行Bean的自动定义. 一, ...

  8. JAVA有关命名规范

    包名:          xxxyyyzzz 全小写 类名/接口名:XxxYyyZzz 所有单词首字母大写,其他小写 方法名:       xxxYyyZzz第一个单词首字母小写,其他单词首字母大写 ...

  9. intellij idea 中添加maven远程仓库

    在intellij idea 中配置好maven后 是这样的 如果加载失败,则需要自定义远程仓库,这里以阿里maven仓库为例, 在项目的pom文件中添加以下配置 <repositories&g ...

  10. 51Nod 1090 3个数之和

    Input示例 7 -3 -2 -1 0 1 2 3 Output示例 -3 0 3 -3 1 2 -2 -1 3 -2 0 2 -1 0 1 #include "bits/stdc++.h ...