JVM学习(五) -执行子系统
虚拟机和物理机的区别。两种都有代码执行能力。物理机的执行引擎是建立在处理器、硬件、指令集和操作系统上。而虚拟机的执行引擎是有自己实现的。因此可以自行的制定指令集和执行引擎的结构关系。
个人理解:分为三个部分。分别是介绍运行时分的各个内存区域【程序计数器、java虚拟机栈【局部变量表、操作数栈、动态链接、方法返回地址】、本地方法栈、方法区、堆】。方法的调用【解析、分派】、方法的执行【解析执行、编译执行】
1. 运行时栈帧结构
栈帧是用于虚拟机进行方法调用和方法执行的数据结构。是虚拟机栈的栈元素。这部分内容和运行内存区域中JAVA虚拟机栈中的栈帧结构部分有重叠的部分。一个栈帧包括局部变量表、操作数栈、动态链接和方法返回地址四部分。栈帧需要多大的局部变量表和多深的操作数栈在编译阶段都已经确定的。
Java虚拟机的解释执行引擎称为“基于栈的执行引擎”,其中的栈指的是操作数栈。
程序计数器、虚拟机栈、本地方法栈都是线程级别的。跟着现成的生而生、跟着线程的灭而灭。意味着,每个线程都有自己的java虚拟机栈。该线程中调用的方法都作为一个栈帧,压栈和弹栈。
(1) 局部变量表
主要用来存储方法的参数和方法内部定义的的局部变量。局部变量表是一组值存储空间。
一个方法只有在调用完成后才会释放。因而,如果一个方法之前定义了大内存的对象,但是,在方法后半部分已经不需要这部分内存了。同时,后半部分需要执行很长时间。这种情况下,会造成前半部分创建的大容量的对象既不被使用需要,又因为方法因为没有执行完成而释放。这部分内存会一致占着不能被释放。所以,也可以在方法内,将不需要继续使用的变量赋值为null。可以让垃圾回收器及时的回收。
(2) 操作数栈
操作数栈的深度在编译的时候已经确定。在方法执行的过程中,从局部变量表中获取数据,压栈。需要计算的时候根据运算符号从栈顶弹栈获得数据进行计算,将结果压栈。
(3) 动态链接
在class文件中,一个方法需要调用其它方法。需要将这些方法的符号引用转换成内存地址中的直接引用。而这些符号引用存在方法区的常量池中。
每个栈的栈帧都包含一个指向运行时常量池中该方法的符号引用。持有这个引用的目的是支持方法调用中的动态链接。
这些符号引用一部分会在类加载阶段或者第一次使用的时候转换成了直接引用。这种转换称为静态解析。另一部分将在每一次运行期间转化成直接引用。这部分称为动态链接。
(4) 方法返回地址
当一个方法开始执行时,可能有两种方式退出该方法。正常完成出口和异常完成出口。
无论方法采用何种方式退出,在方法退出后都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在当前栈帧中保存一些信息,用来帮他恢复它的上层方法执行状态。
2. 方法调用
方法调用并不等同于方法执行,核心任务是:确定被调用方法的版本【即调用的是哪一个方法】。不涉及方法内部的具体执行运行过程。
所有方法之间的调用在class文件中存储的是符号引用。而不是具体方法【实际运行时内存布局的入口地址】的直接引用。需要在类加载甚至在运行期间才能确定目标方法的直接引用。
(1) 解析
调用的目标方法都是方法区的常量池中的一个符号引用。如果程序在真正运行之前就可以确定方法调用的版本,并且这个方法调用的版本在运行期间是不会发生变化的。这种情境下,在类加载的解析阶段,会将符号引用转换成直接引用。这种方法的调用称之为解析。
符合“编译期可知,运行期不可变”的要求的方法,主要包括静态方法和私有方法两大类。前者与类直接关联,后者外部不可被访问。他们特点是不可能通过继承或者其它方式重写其它版本。因此,都会通过解析的方式进行方法调用。
解析对应5条方法调用指令:
① Invoke static :调用静态方法
② Invoke special:调用实例构造器<init>方法,私有方法和父类方法。
③ Invoke virtual:调用所有的虚方法。【final修饰的方法,因为不能被覆盖,没有其它版本,所以,无需对方法进行多态选择】
④ Invoke Interface:调用接口方法(多态)
⑤ Invoke dynamic:
解析是一个静态的过程,在类加载的链接阶段的解析阶段中,就会把涉及的符号引全部转换成直接引用。
(2) 分派
① 静态分派
所有依赖静态类型【参数的声明类型】来定位方法版本的分派称为静态分派。
静态分派最典型的是重载。在编译阶段,根据参数的静态类型就可以确定执行的是哪个版本的方法。静态分派发生在编译阶段,因此,静态分配的动作不由虚拟机来执行。
② 动态分派
运行期间根据实际类型确定方法执行的版本的分派称为动态分派。
动态分派最典型的就是重写。
JVM的invoke virtual指令了,这个指令的解析过程有助于我们更深刻理解重写的本质。该指令的具体解析过程如下
- 找到操作数栈栈顶的第一个元素所指向的对象的实际类型,记为C。【获得实际对象的类型】。
- 如果在类型C中找到与常量中描述符和简单名称都相符的方法,则进行访问权限的校验,如果通过则返回这个方法的直接引用,查找结束;如果不通过,则返回非法访问异常【在C中找和当前方法匹配的方法】
- 如果在类型C中没有找到,则按照继承关系从下到上依次对C的各个父类进行第2步的搜索和验证过程【首先在子类中找,没有再在父类中找。和双亲委派相反,双亲委派优先在父类加载器中处理,而重载优先在子类中匹配】
- 如果始终没有找到合适的方法,则抛出抽象方法错误的异常。
③ 单分派和多分派
(3) 动态类型语言支持
3. 执行引擎
核心理解虚拟机如果执行方法中的字节码指令集。其实就是基于栈的字节码解释执行引擎做的事情。JAVA虚拟机执行代码的时候,都有解释执行【通过解释器执行】和编译执行【通过编译器产生本地代码执行】两种选择。
执行引擎:将字节码指令解析/编译为对应平台上本地机器指令。简而言之,执行引擎充当高级语言和机器码之间的翻译者。
其中,执行引擎中 解释器(interpreter)提供解释执行功能。JIT Completer 提供编译执行的功能。

(1) 解释执行
JVM得到字节码之后。通过解析器Interpreter解析成最终的机器码。
(2) 基于栈的指令集和基于寄存器的指令集
基于栈的指令集:将指令集保存在栈中。大部分是零地址指令集,依赖操作数栈进行工作。Java编译器输出的指令集是基于栈的指令集。
PC电脑支持的就是基于寄存器的指令集。
(3) 基于栈的解释器执行过程
从指令集顺序执行,将局部变量经过操作数栈,最后在局部变量表中生成。运算的过程是从局部变量表获得数据,然后放入操作数栈。从操作数栈弹出进行计算。之后将结果压栈。
先将数放入操作数栈,然后将操作数栈中的数据弹出放入局部变量表中,这样一步步将局部变量表的变量赋值。运算过程中,从局部变量表中获取数据压入操作数栈中。然后根据指令,从操作数栈中弹出数据进行计算,之后将计算结果压栈。
(4) 编译执行
JVM平台提供一种及时编译技术,及时编译的目的是避免函数被解释执行。而是将整个函数体编译成机器码。每次函数执行时,直接执行编译后的机器码。这种方式能将效率大幅提升。
JVM学习(五) -执行子系统的更多相关文章
- jvm学习五: 方法执行过程
方法执行过程:Java各个大版本更新提供的新特性(需要简单了解)
- JVM学习五:JVM之类加载器之编译常量和主动使用
在学习了前面几节的内容后,相信大家已经对JAVA 虚拟机 加载类的过程有了一个认识和了解,那么本节,我们就继续进一步巩固前面所学知识和特殊点. 一.类的初始化回顾 类在初始化的时候,静态变量的声明语句 ...
- JVM学习--(五)垃圾回收器
上一篇我们介绍了常见的垃圾回收算法,不同的算法各有各的优缺点,在JVM中并不是单纯的使用某一种算法进行垃圾回收,而是将不同的垃圾回收算法包装在不同的垃圾回收器当中,用户可以根据自身的需求,使用不同的垃 ...
- JVM学习五:性能监控工具
一.系统性能监控 系统性能工具用于确定系统运行的整体状态,基本定位问题所在. Linux – uptime • 系统时间 • 运行时间 n 例子中为7分钟 • 连接数 n 每一个终端算一个连接 • 1 ...
- JVM学习第三天(JVM的执行子系统)之开篇Class类文件结构
虽然这几天 很忙,但是学习是不能落下的,也不能推迟,因为如果推迟了一次,那么就会有无数次;加油,come on! Java跨平台的基础: 各种不同平台的虚拟机与所有平台都统一使用的程序存储格式——字节 ...
- JVM学习笔记:字节码执行引擎
JVM学习笔记:字节码执行引擎 移步大神贴:http://rednaxelafx.iteye.com/blog/492667
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- 【JVM.8】类加载及执行子系统的案例与实战
一. 案例分析 1. Tomcat:正统的类加载器架构 主流的Java Web服务器,如Tomcat.Jetty.WebLogic.WebSphere或其他服务器,都实现了自己定义的类加载器(一般都不 ...
- JVM性能优化系列-(3) 虚拟机执行子系统
3. 虚拟机执行子系统 3.1 Java跨平台的基础 Java刚诞生的宣传口号:一次编写,到处运行(Write Once, Run Anywhere),其中字节码是构成平台无关的基石,也是语言无关性的 ...
- JVM 的执行子系统
JVM 的执行子系统. 一.Class类文件结构 1. JVM的平台无关性 与平台无关性是建立在操作系统上,虚拟机厂商提供了许多可以运行在各种不同平台的虚拟机,它们都可以载入和执行字节码,从而实现程序 ...
随机推荐
- 063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法
063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法 本文知识点:无参无返回值方法 无参无返回值方法 案例 为什么使用方法?--方便复杂问题调用 ...
- C语言编程入门之--第六章C语言控制语句
导读:本章带读者理解什么是控制语句,然后逐个讲解C语言常用的控制语句,含有控制语句的代码量多起来后就要注意写代码的风格了,本章末节都是练习题,大量的练习才能掌握好控制语句的使用. 6.1 什么是控制语 ...
- CSG:清华大学提出通过分化类特定卷积核来训练可解释的卷积网络 | ECCV 2020 Oral
论文提出类特定控制门CSG来引导网络学习类特定的卷积核,并且加入正则化方法来稀疏化CSG矩阵,进一步保证类特定.从实验结果来看,CSG的稀疏性能够引导卷积核与类别的强关联,在卷积核层面产生高度类相关的 ...
- OpenCV计算机视觉学习(3)——图像灰度线性变换与非线性变换(对数变换,伽马变换)
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 下面 ...
- C#实现迭代器
迭代器模式(Iterator),提供一种方法顺序访问一个聚合对象中的各种元素,而又不暴露该对象的内部表示.C#中使用IEnumerator接口实现,Java中使用Iterator接口实现,其中原理都差 ...
- 持续集成工具之Jenkins pipline简单示例
前文我们主要聊了下jenkins的插件安装.用户及权限管理.邮件发送.配置凭证到gitlab上拉取项目和创建普通job:回顾请参考https://www.cnblogs.com/qiuhom-1874 ...
- 【C++设计模式二】工厂模式
(1)定义3 简单工厂模式中,每新增一个具体产品,就需要修改工厂类内部的判断逻辑.为了不修改工厂类,遵循开闭原则,工厂方法模式中不再使用工厂类统一创建所有的具体产品,而是针对不同的产品设计了不同的工厂 ...
- Pythonic【15个代码示例】
Python由于语言的简洁性,让我们以人类思考的方式来写代码,新手更容易上手,老鸟更爱不释手. 要写出 Pythonic(优雅的.地道的.整洁的)代码,还要平时多观察那些大牛代码,Github 上有很 ...
- 程序3-6 WERTYU
把手放在键盘上时,稍不注意就会往右错一 位.这样,输入Q会变成输入W,输入J会变成输 入K等.键盘如图3-2所示. 输入一个错位后敲出的字符串(所有字母均 大写),输出打字员本来想打出的句子.输入保 ...
- super函数
Python面向对象中super用法与MRO机制:https://www.cnblogs.com/chenhuabin/p/10058594.html python 中 super函数的使用:http ...