java中 u0038_【0038】浅析Java虚拟机字节码执行引擎

前言

执行引擎是Java虚拟机的核心组成部分之一,其模型使用IPO概念解读为:输入的是字节码文件、处理过程是等效字节码解析过程,输出的是执行结果。既然是执行字节码,必然有一个入口,对于程序而言那就是方法的调用执行,而方法调用和运行的基本单位是栈帧,所以下文会先介绍栈帧结构和方法调用,最后在分析虚拟机的字节码执行引擎。

本文大纲:

1、运行时栈帧结构

2、方法调用

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

4、总结

一、运行时栈帧结构

应用程序运行时会为每个线程创建一个栈,在调用方法时会在相应栈中创建一个栈帧。栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构。每个栈帧都包括了一下几部分:局部变量表、操作数栈、动态连接、方法返回地址和附加信息。栈帧结构图如下:

68bfdf3476ef0c6acd06a67b23f67ce1.gif

1.1 局部变量表

局部变量表就是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。

局部变量表的容量以变量槽(slot)为最小单位,每个slot都应该能存放一个boolean,byte,short,int,char,float,reference,returnAddress类型的数据,对于64位的数据类型只有double,long两种(reference可能为32位也可能为64位),这两种类型占用两个连续slot。

虚拟机是使用局部变量表完成参数值到参数变量列表的传递过程,如果是实例方法(非static)那么局部变量表中第0位索引的slot默认是用于传递方法所属对象实例的引用,方法中可以通过this来访问这个隐含的参数。其余参数则按照参数表的顺序来排列,占用从1开始的局部变量slot,参数表分配完毕之后,再根据方法体内部定义的变量顺序和作用域分配其余的slot。

类变量有两次赋值的过程,一次在准备阶段,赋予系统初始值(比如int默认值为0,boolean默认值为false,object类型默认值为null等),另外一次在初始化阶段,赋予程序员定义的初始值。因此即使在初始化阶段程序员没有为类变量赋值也没用关系,类变量仍然具有一个确定的初始值。但是局部变量若是定义了但没有赋初始值是没法使用的,类加载将会失败,但是主流开发IDE在编译阶段就会提示我们程序编译失败,比如:Elipcse。

1.2 操作数栈

操作数栈是一个后入先出栈,是用来进行存储方法在执行的过程中的一些指令的操作数和中间值的场所,在方法执行的过程中,会有各种的字节码指令往操作数栈中写入和读取内容,也就是出栈和入栈操作。

同时这也是相对于基于寄存器的虚拟机的弱势,因为每次的出栈和入栈操作无疑多了很多的操作,造成数据的读取和写入比较繁琐,速度上是比基于寄存器的虚拟机要慢的,但是可移植性较好。Java虚拟机的解释执行引擎为“基于栈的执行引擎”,其中的栈指的就是操作数栈。

1.3 动态连接

每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用就是为了支持方法调用过程中的动态连接。

这些符号引用会在类加载阶段或者第一次使用的时候就转化为直接引用,这种转化成为静态解析。另外一部分将在每一次运行期间转化为直接引用,这部分称为动态连接。这两个过程就是方法调用过程的两种方式。

1.4 方法返回地址

方法被执行后,有两种方式退出这个方法。第一种方法是执行引擎遇到任意一个方法的返回的字节码指令。另外一种退出方式是在方法执行过程中遇到了异常,并且这个异常并没有在方法体中得到处理。

方法退出之后,需要返回到方法被调用的位置,程序才能继续执行,方法返回时需要在栈帧中保存一些信息,用以帮助它恢复它上层方法的执行状态。一般情况下,调用者的pc计数器的值可以作为返回地址,栈帧中很可能会保存这个计数器值,方法异常退出时,返回地址是要通过异常处理器表来确定,栈帧中一般不会保存这部分信息。

方法退出的过程实际上等同于把当前栈帧出栈,所以可能需要执行这些操作:恢复上层方法的局部变量表和操作数栈,把返回值压入调用者栈的操作数栈中,调整pc计数器的值。

1.5 附加信息

虚拟机规范允许具体的虚拟机实现增加一些虚拟机规范里面没有描述的信息到栈帧之中,例如与调试相关的信息。一般将动态连接、方法返回地址和其他附加信息全部归为一类,称为栈帧信息。

二、方法调用

方法调用的主要任务就是确定被调用方法的版本(即调用哪一个方法),该过程不涉及方法具体的运行过程。按照调用方式共分为两类:

2.1 解析调用

在类加载的解析阶段,会将其中的一部分符号引用转化为直接引用,这种解析能成立的前提是,方法在程序真正运行之前就有一个可确定的调用版本,并且这个方法的调用版本在运行期是不可改变的。符合这个条件的有静态方法,私有方法,实例构造器和父类方法四类,它们在类加载的时候会把符号引用解析为该方法的直接引用。

解析调用一定是一个静态的过程,编译期间就完全确定,在类装载的解析阶段就会把涉及到的符号引用全部转化为可确定的直接引用,不会延迟到运行期间再去完成。

2.2 分派调用

分派调用可能是静态的也可能是动态的,分派机制与java的多态机制关系密切。

静态分派:依赖静态类型来定位方法执行版本的分派动作,称为静态分派。静态分派的最典型的应用就是方法重载。静态分派发生在编译阶段,因此确定静态分派的动作实际上不是由虚拟机来执行的。

动态分派:在运行期间根据实际类型来确定方法执行版本的分派调用过程称为动态分派。这跟多态性的另一个特性重写有着很密切的关联。

2.3静态分派案例

68bfdf3476ef0c6acd06a67b23f67ce1.gif

68bfdf3476ef0c6acd06a67b23f67ce1.gif

执行结果是:

hello guy

hello guy

原因:虚拟机在重载时是通过参数的静态类型而不是实际类型作为判定依据,并且静态类型是编译期可知的,所以在编译阶段,javac编译器就根据参数的静态类型决定使用哪个重载版本,并把这个方法的符号引用写入invokevirtual指令的参数中。Man实例和Woman实例都是使用Human这个静态类型声明。

2.4 动态分派案例

68bfdf3476ef0c6acd06a67b23f67ce1.gif

68bfdf3476ef0c6acd06a67b23f67ce1.gif

执行结果:

man say hello

woman say hello

woman say hello

原因:invokevirtual指令有多态查找的机制,会根据实际类型来调用方法,而不是声明的参数类型。

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

Java虚拟机的字节码执行引擎可以说是基于栈的字节码解释执行引擎,这里的栈指的是操作数栈,为什么是解释执行呢?原因是先解析字节码文件再执行的。但是也不严格,现今的即时编译器可以编译执行,只能说大部分时候是解释执行。

Java语言常被人说是一种“解释执行”的语言,与C语言等编译执行的语言不一样。

68bfdf3476ef0c6acd06a67b23f67ce1.gif

在Java语言中,Javac编译器完成了程序代码经过词法分析、语法分析到抽象语法树,再遍历语法树生成线性的字节码指令流的过程。程序运行时通过解析字节码指令流运行程序。

其次,Java虚拟机使用的是基于栈的指令集,而不是基于寄存器的指令集,这两种指令集有什么区别呢?其实就是Java与C之间的区别,可移植性的不同。基于栈的指令集不依赖于具体的操作系统,而基于寄存器的指令集与操作系统底层关系密切。

四、总结

简单总结一下,本文主要介绍了Java虚拟机的字节码执行引擎,其执行方式是解释执行为主。同时介绍了运行时栈帧的结构以及方法是如何被调用的,调用的方式有解析调用和分派调用两种,而分派调用又包括静态分派和动态分派。静态分派与多态中的重载对应,动态分派与多态中的重写对应。

感谢您的阅读,谢谢。

参考文献:《深入理解Java虚拟机》作者:周志明

始发于微信公众号: Java框架源码分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像的目标属于哪个类别。 定位问题:确定目标在图像的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值