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的平台无关性 与平台无关性是建立在操作系统上,虚拟机厂商提供了许多可以运行在各种不同平台的虚拟机,它们都可以载入和执行字节码,从而实现程序 ...
随机推荐
- 【题解】[USACO12MAR]Cows in a Skyscraper G
题目链接 题目大意:给定一个集合\(S\),给一个限制条件\(P\),要求划分集合,使得每一个子集\(A\in S\),\(A\)满足限制条件\(P\),且划分总数最小. 注意到数据范围\(n< ...
- 【题解】[CH弱省胡策R2]TATT
本蒟蒻第一道\(K-D-Tree\)维护\(dp\) Question 题目大意:求一条路径,使得其四个维度单调不降. 先排序消掉一维再说. 对于每一个点,初始的时候绝对长度是1啊.于是,先赋值一个1 ...
- 这就是小学生也会用的四则计算练习APP吗?- by软工结对编程项目作业
结对编程项目 软件工程 这就是链接 作业要求 这就是链接 作业目标 熟悉在未结对情况下如何结对开发项目 Github与合作者 合作者(学号): 区德明:318005422 虚左以待 Github链接: ...
- dockerfile-maven-plugin极简教程
目录 一.简介 二.概述 三.将spring-boot-app打包成docker镜像 创建示例应用 修改pom文件 增加Dockerfile文件 使用Maven打包应用 运行应用镜像 四.分析mvn ...
- 架构师根本不会被语言限制住,php照样可以用领域驱动设计DDD四层架构!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 你在通往架构师的路上吗? 程序员这个行业就像是在不断的打怪升级,突破每一阶段的瓶颈期 ...
- 对NETIF_F_GSO的一些理解
看linux内核协议栈的时候看到tcp_sendmsg函数,看起来并不难理解,但是申请skb的时候主buff大小让我很困惑.我以前一直以为会根据sack/ip option/pmtu等计算一个mss, ...
- MeteoInfoLab脚本示例:OMI Grid HDF数据
OMI卫星格点数据的例子,全球臭氧柱总量分布.脚本程序: #Add data file folder = 'D:/Temp/hdf/' fns = 'OMI-Aura_L3-OMTO3e_2005m1 ...
- 【C语言C++编程入门】——程序结构:构思!
学习编程语言的最好方法是编写程序.一般来说,初学者编写的第一个程序是一个名为"Hello World"的程序,它简单地将"Hello World"打印到你的电脑 ...
- PHP字符串如何转换成if条件语句
例如: $condition = "2 == 2 && 3 == 5"; if ( $condition ){ echo 1; } 怎样把 $condition 转 ...
- 第二十二章 Nginx性能优化
一.性能优化概述 1.我们需要了解 1.首先需要了解我们当前系统的结构和瓶颈,了解当前使用的是什么,运行的是什么业务,都有哪些服务,了解每个服务最大能支撑多少并发.比如nginx作为静态资源服务并发是 ...