虚拟机字节码执行引擎

7人阅读 评论(0) 收藏 举报
分类:

读深入理解JAVA虚拟机 第八章,记一下内容

虚拟机字节码执行引擎

概述

执行引擎在执行java代码的时候会有解释执行(通过解释器执行)和编译执行(通过即使编译器产生本地代码执行)两种选择,也可能两者兼备。

运行时栈帧结构

每一个栈帧都包括了局部变量表,操作数栈,动态连接,方法返回地址和一些额外的附加信息。
1,每个栈帧需要分配的内存大小,都是在编译代码的时候就已经确定并且写入到方法表的code属性中了。
2,在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与整个栈帧相关联的方法称为当前方法。执行引擎运行的所有字节码指令都只针对当前栈帧进行操作。

局部变量表

一组变量值存储空间,存放方法参与和方法内部定义的局部变量
局部变量表的容量以变量槽(Variable Slot)为最小单位,虚拟机没有规定一个Slot应占内存空间的大小,但是每个slot都应该能存放一个基本数据类型(int,float,byte,boolean,char,short),或者返回地址类型或者reference类型(对象实例的引用),这八种类型(不包括long,String),这八种类型都可以用32位或者更小的物理内存来存放,但是没有规定大小,这样虚拟机如果是64位的,也可以用64位去实现slot,然后用空白区域补齐多余的32位空间;

线程私有的;

slot的空间是在内存中真实分配的,这个空间是可以被局部变量重复使用的,如果有一个局部变量a,在代码块之中,现在在代码块之外,所以这时候如GC,理论上是能回收a所指向的内存的,但是如果slot没有进行任何操作,那么slot还是指向了这个内存的,所以GC的时候,会发现内存不能释放,因为还在被占用;

slot没有任何操作是指,在期间没有任何对局部变量表的读写操作,占用的slot还没有被其他变量复用;

所以如果碰见这种不在使用但是又占据大内存的操作,并且可能后面要进行一个长耗时的操作,并没有去复用这个slot,那么可以考虑手动把这个变量设置为null来释放内存。(不优雅,平时不用考虑)

代码只有在解释器执行时候才会有上述的回收情况,如果是JIT编译器编译,优化后的,这个赋null值的动作会被消除,而且代码也不会有这个gc问题,所以不需要用赋值的方式来清空旧代码;
字节码被编译为本地代码后,对GC Roots的枚举与解释执行期有巨大差别。

局部变量没有经过赋值(初始化)是不存在默认值的,所以是不能编译成功的

方法返回地址

当一个方法开始执行后,只有两种方式可以退出这个方法
正常完成退出:(Normal Method Invocation Completion),执行引擎遇到任意一个方法方法的字节码指令,将返回值传递给上层的方法调用者(是否有返回值以及返回值类型将根据遇到的是哪种方法返回指令来决定)
异常完成出口:(Abrupt Method Invocation Completion)在方法执行过程中遇到了异常,并且没有在方法体内得到处理,一个方法使用异常完成出口的方式退出,是不会给它的上层调用者产生任何返回值的。

方法调用

方法调用阶段唯一的任务就是确定被调用方法的版本(调用哪一个方法),只是符合引用,不包括传统编译中的连接步骤(直接引用地址)

解析

在类加载的解析阶段,会将一部分的符合引用转化为直接引用,前提是,在方法程序真正运行之前,也就是方法调用阶段,就有一个可以确定的,并且在运行期不会改变的调用版本。
“编译器可知,运行期不可变”的主要有
静态方法,私有方法,实例构造器,父类方法4个类型,它们在类加载的时候就会把符号引用转化为直接引用。这些方法叫做非虚方法,final修饰的因为不能改变,所以也是一种非虚方法
其他方法叫做 虚方法(不含final的方法)。

分派

分派调用,(Dispatch)可能是静态的,也可能是动态的,分为单分派和多分派,以及静态vs动态,四种情况

静态分派

Human man = new Man();

这里的Human称为变量的静态类型/外观类型,后面的Man称为变量的实际类型

虚拟机(编译器)在重载时是通过参数的静态类型而不是实际类型作为判断依据的。静态类型是编译器可知的,而实际类型变化的结果要在运行期才可以确定。

所有依赖静态类型来定位方法执行版本的分派动作称为静态分派。典型应用就是重载。
有时候,这种重载方法的版本不是“唯一”的,所以只是选了一个“更适合的”版本
比如说,调用的时候如下甚至更多情况,会先选char,没有char的时候,会选int,按照char->int->long->float->double的顺序进行自动类型转换,选择优先级高的方法版本;

再下一个优先级是Character,字段类型转换找不到的情况下,就进行自动装箱,然后是接口类型,比如Serializable;

可变长参数的优先级是最低的;同时在单参数中可以成立的一些自动类型转换,在可变长参数中是不成立的。

在现实中不应该出现这种极端代码。太绕
具体看P250页。

sayHello('a');
public static void sayHello(int arg){...}
public static void sayHello(char arg){...}

动态分派

静态类型和实际类型一样,(都是子类Man)子类和父类中都有同名方法,先找子类,子类没有就找父类的方法,这个就是动态了。
运行期根据实际类型确定方法执行版本的分派过程称为动态分派。

宗量:子类和父类重载选择是一种,同方法类同名函数的重写也是一种,两种宗量
静态分派属于多分派类型
动态分配数单分派类型(具体看P256)

虚拟机的优化手段:为类在方法区中建立一个虚方法表(Vritual Method Table,vtable)以及对应的接口方法表(Interface Method Table, itable)。使用虚方法表索引来代替元数据查找以提高性能。
存放了各个方法的实际入口,如果子类重写了父类方法,子类方法表中的地址将会被替换为指向子类实现版本的入口地址,如果没有重写,就是指向父类的实现入口地址。

动态类型语言

动态类型语言:比如php,JavaScript,特点,“变量无类型,而变量值才有类型”,灵活

静态类型语言:比如java,c++,需要在编译器确定(变量)类型,严谨检查

invoke包,MethodHandle 动态确定目标方法的机制。

基于栈的字节码解释执行引擎

分为解释代码执行和编译(本地代码)执行
大致流程:
程序源码->词法分析->单词流->语法分析->抽象语法树

解释执行的情况: ->指令流(可选)->解释器->解释执行
编译执行的情况: ->优化器(可选)->中间代码(可选)->生成器->目标代码

执行过程的字节码略 P.273

实际情况中,虚拟机中解析器和即使编译器都会对输入的字节码进行优化,所以运行的时候,都会比概念模型来的性能更高。或者描述的差距很大

查看评论

深入JVM字节码执行引擎

我们都知道,在当前的Java中(1.0)之后,编译器讲源代码转成字节码,那么字节码如何被执行的呢?这就涉及到了JVM的字节码执行引擎,执行引擎负责具体的代码调用及执行过程。...
  • dd864140130
  • dd864140130
  • 2015-10-30 18:57:11
  • 8488

Java虚拟机字节码执行引擎浅析

执行引擎是Java虚拟机的核心组成部分之一。     我们知道,javac编译器完成了程序代码经过词法分析、语法分析到抽象语法树、再遍历语法树生成线性的字节码指令流的过程。而字节码文件再经过加载...
  • kobejayandy
  • kobejayandy
  • 2014-09-27 23:13:15
  • 3235

深入理解Java虚拟机:虚拟机字节码执行引擎

概述    在不同的虚拟机实现里面,执行引擎在执行Java代码的时候可能有解释执行和编译执行两种选择,也可能两者兼备,甚至还可能包含几个不同级别的编译器执行引擎。但从外观上,所有的Java虚拟机的执行...
  • LittleCoding
  • LittleCoding
  • 2017-03-05 20:47:45
  • 227

java虚拟机字节码执行引擎浅析

执行引擎是java虚拟机的核心组成部分之一。     我们知道,javac编译器完成了程序代码经过词法分析、语法分析到抽象语法树、再遍历语法树生成线性的字节码指令流的过程。而字节码文件再经过加载...
  • RowandJJ
  • RowandJJ
  • 2014-04-11 19:30:46
  • 2296

Java虚拟机之字节码执行引擎

1 概述虚拟机执行引擎是Java虚拟机最核心的部分之一,其目的是实现:输入字节码文件,将字节码解析或等效处理后,执行并输出结果。其中两种执行方式:解释执行和编译执行。2 运行时栈帧结构栈帧(Stack...
  • felix_wangq
  • felix_wangq
  • 2016-01-26 09:35:47
  • 685

深入理解JVM-字节码执行引擎

前面我们不止一次的提到,Java是一种跨平台的语言,为什么可以跨平台,因为我们编译的结果是中间代码—字节码,而不是机器码,那字节码在整个Java平台扮演着什么样的角色的呢?JDK1.2之前对应的结构图...
  • u012077981
  • u012077981
  • 2014-10-16 21:23:42
  • 2906

[深入理解Java虚拟机]第八章 字节码执行引擎-基于栈的字节码解释执行引擎

许多Java虚拟机的执行引擎在执行Java代码的时候都有解释执行(通过解释器执行)和编译执行(通过即时编译器产生本地代码执行)两种选择,在本章中,我们先来探讨一下在解释执行时,虚拟机执行引擎是如何工作...
  • qilixiang012
  • qilixiang012
  • 2015-10-26 00:52:50
  • 633

虚拟机字节码执行引擎的方法调用

方法调用的主要任务就是确定被调用方法的版本(即调用哪一个方法),该过程不涉及方法具体的运行过程。class文件的编译过程中不包含传统编译中的连接步骤,一切方法调用在class文件中存储的都是符号引用,...
  • limerick1718
  • limerick1718
  • 2017-02-03 20:31:43
  • 147

java虚拟机字节码执行引擎之方法调用

方法调用阶段唯一的任务是确定被调用方法的版本,即调用哪一个方法. 一切方法调用在Class文件里面存储的都只是符号引用,不是方法在实际运行时内存布局中的入口地址,需要在类加载期间,甚至到运行期间才能确...
  • u013014724
  • u013014724
  • 2016-11-17 11:09:10
  • 321

深入理解Java虚拟机----(七)字节码执行引擎

执行引擎是最重要的一部分,概念模型的总体外观是一致的:输入自己吗,过程是字节码解析的等效过程,输出结果。不同的虚拟机有不同的具体实现,大体有解释执行和编译执行两种选择。 运行时栈帧结构:     ...
  • wl6965307
  • wl6965307
  • 2016-02-12 11:49:39
  • 1593
    个人资料
    等级:
    访问量: 124
    积分: 90
    排名: 121万+
    文章存档