`
阅读更多
执行引擎是 java 虚拟机最核心的组成部分之一.在虚拟机规范中制定了虚拟机字节码执行引擎的概念模型,这个概念模型称为各种虚拟机执行引擎的统一外观. 在不同的虚拟机实现里,执行引擎在执行 java 代码的时候,可能会解释执行和编译执行等,但是从外观上来看,所有的 java 虚拟机的执行引擎都是一致的:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.

运行时栈帧结构

栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素.栈帧中存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息.

每个方法从调用开始到执行完成,对应着栈帧从入栈到出栈这么一个过程.

每一个栈帧都包括局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息. 在编译程序代码的时候,栈帧中需要多大的局部变量表,多深的操作数栈都是一件完全确定的,并且写入到方法表的 Code 属性中,因此一个栈帧需要多大的空间,不受程序运行期间变量数据的影响.

一个线程中方法调用链可能会很长,很多方法都同时处于执行状态.对于执行引擎来说,在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法. 执行引擎运行的所有字节码指令都只针对当前栈帧进行操作,在概念模型上,典型的栈帧结构:




局部变量表:是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量. 在 java 程序被编译为 Class 文件时,就在方法的 Code 属性的 max_locals 数据项中确定了该方法所需分配的局部变量表的最大容量.
局部变量表的基本单位是 slot,虚拟机规范中并没有明确指明一个 Slot 应占用多大的内存空间大小,只是很有导向性地说到每个 Slot 都应该能存放一个 boolean、byte、char、short、int、float、reference 或 returnAddress 类型的数据.

为了尽可能的节省栈帧空间,局部变量表中的 Slot 是可以重用的,方法体中定义的变量,其作用域并不一定会覆盖整个方法体,如果当前字节码PC计数器已经超过了某个变量的作用域,那么这个变量对应的 Slot 就可以交给其他变量使用. 但是这会有一个坏处,Slot 复用可能会影响到系统的垃圾收集行为.

局部变量和类变量不同,如果局部变量定义了但是没有赋初始值的话是不能使用的,不要认为 java 中任何情况下都存在诸如整型变量默认为 0,布尔变量默认为 false 这样的默认值.


操作数栈:同局部变量表一样,操作数栈的最大深度也在编译的时候写到了 Code 属性的 max_stacks 数据项中. 操作数栈的每个元素可以是任意的 java 数据类型,包括 long 和 double. 32 位数据类型所占的栈容量为 1,64 为数据类型所占的栈容量为 2. 在方法执行的任何时候,操作数栈的最大深度都不会超过在 max_stacks 数据项中设定的最大值.

当一个方法刚开始执行的时候,这个方法的操作数栈是空的,在方法的执行过程中,会有各种字节码指令往操作数栈中写入和提取内容,也就是出栈/入栈操作.

整数加法的字节码指令 iadd 在运行的时候操作数栈中最接近栈顶的两个元素已经放入了两个 int 型的数值,当执行这个指令时,会将这两个 int 值出栈并相加,然后将将相加结果入栈.

在概念模型中,两个栈帧是完全互相独立的,但是大多数虚拟机的实现里会做一些优化处理,令两个栈帧出现一部分重叠.



动态链接

每个栈帧都包含一个执行运行时常量池中该栈帧所属方法的引用,持有这个引用就是为了支持方法调用过程中的动态链接. 我们知道 Class 文件常量池中存在大量的符号引用,这些符号引用一部分会在类加载阶段或者第一次使用的时候就转化为直接引用,这个转化称为静态解析.另一部分将在每次运行期间转化为直接引用,这部分称为动态链接.

方法返回地址

当一个方法开始执行后,只有两种方式可以退出这个方法. 第一种是执行引擎遇到任意一个方法返回的字节码指令,这时候可能会有返回值传递给上层的方法调用者.另一种是方法在执行的过程中遇到了异常,并且这个异常没有在方法体内得到处理. 一个方法异常退出,是不会给它的上层调用者产生任何返回值的.

无论采用何种退出方式,在方法退出后,都需要返回到方法被调用的位置,程序才能继续执行,方法返回时可能需要在栈帧中保存一些信息,用来帮助恢复它的上层方法的执行状态. 一般来说,方法正常退出时,调用者的 PC 计数器的值可以作为返回地址,栈帧中很有可能会保存这个计数器值. 而方法异常退出时,返回地址是要通过异常处理器表来确定的,栈帧中一般不会保存这部分信息.

方法退出时可能执行如下行为:恢复上层方法的局部变量表和操作数栈,把返回值(如果有的话)压入调用者栈帧的操作数栈中,调整PC计数器的值以指向方法调用指令后面的一条指令等.

附加信息

虚拟机规范允许具体的虚拟机实现增加一些规范里没有描述的信息到栈帧中,例如与调试相关的信息,这部分信息完全取决于具体的虚拟机实现.





0
0
分享到:
评论

相关推荐

    虚拟机运行时栈帧的结构

    运行时栈帧结构 栈帧是用于支持虚拟机进行方法调用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素.栈帧中存储了方法的局部变量表、操作数栈、动态链接和方法返回地址等信息. 每个方法从调用开始...

    15.运行时栈帧结构1

    运行时栈帧结构是Java虚拟机(JVM)中的一种数据结构,用于支持虚拟机进行方法调用和方法执行。每个方法的调用开始到结束都对应着一个栈帧在虚拟机栈中的入栈到出栈的过程。栈帧中包括了局部变量表、操作数栈、动态...

    javase8虚拟机结构

    栈帧(Stack Frame)是用于支持虚拟机方法调用的一种数据结构,它包含方法的局部变量表、操作数栈、动态链接信息以及返回地址等。栈帧的生命周期与方法调用紧密相关:当方法被调用时创建新的栈帧,方法执行完毕后栈帧...

    Java虚拟机栈--栈帧.docx

    理解Java虚拟机栈和栈帧的内部结构对于优化代码性能、理解和解决内存溢出等问题至关重要。开发者可以通过反编译工具,如`javap`,或者IDE插件(如jclasslib byte viewcoder)来查看和分析字节码文件,以深入了解栈帧...

    深入java虚拟机(一)——java虚拟机底层结构详解1

    Java虚拟机(JVM)是Java程序运行的核心组件,它为Java代码提供了跨平台的运行环境。JVM的底层结构主要包括几个关键部分:寄存器、栈和堆。 首先,JVM寄存器是虚拟机内部的一个概念,尽管实际硬件可能不包含与之...

    虚拟机内存结构和垃圾回收docx.pdf

    《虚拟机内存结构和垃圾回收》 Java的垃圾回收(Garbage Collection,简称GC)机制是其与C++等语言的重要区别,它自动处理内存的分配与回收,减轻了程序员的负担。然而,理解GC的工作原理对于优化应用程序性能至关...

    Java虚拟机(内存结构)1

    Java虚拟机(JVM)是Java程序运行的核心,它的内存结构是理解Java性能优化和内存管理的关键。在Java虚拟机中,内存分为多个区域,主要包括以下几个部分: 1. **原始类型**:Java语言中,原始类型包括数值类型(如...

    JAVA 11 虚拟机规范

    Java虚拟机规范是一套详细描述Java虚拟机(JVM)结构和行为的文档,其目的是让Java语言能够在不同的平台上运行,同时保持“一次编写,到处运行”的承诺。在Java 11版本中,虚拟机规范进行了更新,提供了对Java 11...

    java虚拟机结构机制.rar

    本资料将深入探讨Java虚拟机的结构机制,包括内存区域、指令集、垃圾回收、类加载机制等关键概念。 1. **内存区域**: - **程序计数器**:存储当前线程正在执行的字节码的地址,用于控制程序的执行流程。 - **...

    JVM中[虚拟机栈]的所有内容-pdf

    同时,局部变量表中的变量也是垃圾回收的根节点,只要被局部变量表引用的对象都不会被回收,因此理解栈帧结构有助于理解内存管理和垃圾收集机制。 总结来说,Java虚拟机栈是Java程序执行的基础,它管理着方法调用的...

    Java虚拟机的基本结构 (2)1

    2. **Java虚拟机栈(Java Virtual Machine Stacks)**:同样为线程私有,每当线程执行一个方法时,就会在虚拟机栈中创建一个栈帧。栈帧存储了局部变量表、操作数栈、动态链接以及方法返回地址等信息。局部变量表主要...

    Java虚拟机规范.Java SE 8版

    第2章概述Java虚拟机的整体架构,包括class文件格式、数据类型、原始类型、引用类型、运行时数据区、栈帧、浮点算法、异常等,这对理解本书后面的内容有重要帮助;第3章详述如何将Java语言编写的程序转换为Java...

    Java虚拟机 JVM 内存结构介绍

    Java虚拟机(JVM)内存结构是理解Java应用程序性能和内存管理的关键。本文将详细介绍JVM内存的不同组件,包括它们的功能和重要性。 首先,Java虚拟机规范中的内存管理主要涉及Runtime Data Area,这是一个用于存储...

    JVM虚拟机面试题汇总

    栈帧结构如下: - **局部变量表(Local Variable Table)**:用于存放编译期可知的各种基本数据类型、对象引用等。 - **操作数栈(Operand Stack)**:主要用于保存计算过程中产生的中间结果,也用来存放操作数。 - *...

    深入JAVA虚拟机 随书源码 JVM规范

    首先,我们来看《深入JAVA虚拟机》这本书,它涵盖了JVM的各个关键方面,包括指令集、运行时数据区、方法区、堆内存、栈帧结构、编译与优化、异常处理和安全性等。书中通过实例解析,帮助读者理解JVM如何处理Java程序...

    Java虚拟机规范PDF

    - **虚拟机栈**:描述的是Java方法执行的内存模型:每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。 - **本地方法栈**:与虚拟机栈类似,但为虚拟机使用到的Native...

    Java虚拟机规范(Java SE 7)中文版

    第2章概览了Java虚拟机整体架构,包括class文件格式、数据类型、原始类型、引用类型、运行时数据区、栈帧、浮点算法、异常等,这对理解本书后面的内容有重要帮助。第3章详述如何将Java语言编写的程序转换为Java...

Global site tag (gtag.js) - Google Analytics