运行时数据区——Java虚拟机栈

简介:  与程序计数器一样, Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。

 

与程序计数器一样, Java虚拟机栈(Java Virtual Machine Stacks)也是线程私有的,它的生命周期与线程相同。Java栈以帧为单位保存线程的运行状态。每个方法在执行的时候都会创建一个栈帧用于存储局部变量表、操作栈、动态链接、 方法出口等信息。虚拟机只会直接对Java栈执行两种操作: 以帧为单位的压栈或出栈。

 

Java方法可以以两种方式完成。一种通过return返回,称为正常返回;一种是通过抛出异常而中止的。不管以哪种方式返回,虚拟机都会将当前帧弹出Java栈然后释放掉,这样上一个方法的帧就成为当前帧了。

Java栈上的所有数据都是此线程私有的。任何线程都不能访问另一个线程的栈数据, 因此我们不需要考虑多线程情況下栈数据的访问同步问题。当一个线程调用一个方法时,方法的局部变量保存在调用线程Java栈的帧中 。只有一个线程能总是访问那些局部变量, 即调用方法的线程 。

像方法区和堆一样, Java栈和帧在内存中也不必是连续的 。帧可以分布在连续的栈里,也可以分布在堆里, 或者二者兼而有之。 表示Java栈和栈帧的实际数据结构由虚拟机的实现者决定, 某些实现允许用户指定Java栈的初始大小和最大最小值。

局部变量表

局部变量表存放了编译期可知的各种基本数据类型(boolean、 byte、 char、 short、 int、float、long、 double)、对象引用(reference类型,它不等同于对象本身,根据不同的虚拟机实现, 它可能是一个指向对象起始地址的引用指针, 也可能指向一个代表对象的句柄或者其他与此对象相关的位置) 和 retunAddress类型 (指向了一条字节码指令的地址)。

局部变量表是一组变量值存储空间,用于存放方法参数和方法内部定义的局部变量。Java栈帧的局部变量表被组织为一个以字长为单位,从0开始计数的数组。虚拟机通过索引定位的方式使用局部变量表, 编译器首先按声明的顺序把这些参数放入局部变量数组。 字节码指令通过从0开始的索引来使用其中的数据。类型为int、 float、 reference和returnAddress的值在数组中只占据一项, 而类型为byte、 short和char的值在存入数组前都将被转换为int值, 因而同样占据一项。 但是类型为long和double的值在数组中占据连续的两项。

在访问局部变量中的long和double值的时候, 只需取出连续两项中第一项的索引值。 例如某个long值占据第3、 4项, 那么指令会取索引为3的long值。 局部变量区的所有值都是字对齐的, long和double这样占据两项数组元素的值同样可以起始于任何索引 。

下面通过两个例子及图示说明下局部变量区:

public static int runClassMethod(int i,long l,float f,double d,Object o,byte b) { 
   return 0;   
}
public int runInstanceMethod(char c,double d,short s,boolean b) { 
       return 0;   
}

如果是实例方法(非 static的方法), 那么局部变量表中第 0位素引的 Slot默认是用于传递方法所属对象实例的引用, 在方法中可以通过关键字 “this'' 来访问这个隐含的参数。其余参数则按照参数表的顺序来排列,占用从1开始的局部变量Slot。

操作数栈

和局部变量表一样,操作数栈也被组织成一个以字长为单位的数组。可以把操作数栈理解为存储计算时,临时数据的存储区域。虚拟机在操作数栈中存储数据的方式和在局部变量区中是一样的。

但和前者不同,它不是通过索引来访问的,而是通过压栈和出栈来访问的。操作数栈的毎一个元素可以是任意的 Java数据类型, 32位数据类型所占的栈容量为1, 64位数据类型所占的栈容量为2。

Java 虚拟机的指令是从操作数栈中而不是从寄存器中取得, 因此它的运行方式是基于栈的而不是基于寄存器的 。

虚拟机把操作数栈作为它的工作区——大多数指令都要从这里弹出数据, 执行运算, 然后把结果压回操作数栈。

动态链接

毎个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用, 持有这个引用是为了支持方法调用过程中的动态连接。 Class文件的常量池中存有大量的符号引用, 字节码中的方法调用指令就以常量池中指向方法的符号引用为参数。 这些符号引用一部分会在类加载阶段或第一次使用的时候转化为直接引用,这种转化称为静态解析。 另外一部分将在毎一次的运行期间转化为直接引用 , 这部分为动态连接。

参考:

https://iamjohnnyzhuang.github.io/java/2016/07/12/Java%E5%A0%86%E5%92%8C%E6%A0%88%E7%9C%8B%E8%BF%99%E7%AF%87%E5%B0%B1%E5%A4%9F.html

 

 

 

 

相关文章
|
2月前
|
Linux 虚拟化 iOS开发
VMware Fusion 13.6.4 OEM BIOS 2.7 - 在 macOS 中运行 Windows 虚拟机的最佳方式
VMware Fusion 13.6.4 OEM BIOS 2.7 - 在 macOS 中运行 Windows 虚拟机的最佳方式
300 3
|
4月前
|
存储 安全 Java
JVM深入原理(七)(一):运行时数据区
栈的介绍:Java虚拟机栈采用栈的数据结构来管理方法调用中的基本数据,先进后出,每一个方法的调用使用一个栈帧来保存栈的组成:栈:一个线程运行所需要的内存空间,一个栈由多个栈帧组成栈帧:一个方法运行所需要的内存空间活动栈帧:一个线程中只能有一个活动栈帧栈的生命周期:栈随着线程的创建而创建,而回收会在线程销毁时进行栈的执行流程:栈帧压入栈内执行方法执行完毕释放内存若方法间存在调用,那么会压入被调用方法入栈,执行完后释放内存,再执行当前方法,直到执行完毕,释放所有内存。
68 0
|
4月前
|
存储 缓存 安全
JVM深入原理(七)(二):运行时数据区
堆的作用:存放对象的内存空间,它是空间最大的一块内存区域.栈上的局部变量表中,可以存放堆上对象的引用。静态变量也可以存放堆对象的引用,通过静态变量就可以实现对象在线程之间共享。堆的特点:线程共享:堆中的对象都需要考虑线程安全的问题垃圾回收:堆有垃圾回收机制,不再引用的对象就会被回收方法区的概述:方法区是存放基础信息的位置,线程共享,主要包括:类的元信息:保存了所有类的基本信息运行时常量池:保存了字节码文件中的常量池内容静态常量池:字节码文件通过编号查表的方式找到常量。
60 0
|
6月前
|
监控 网络安全 虚拟化
Hyper-V中Win10,虚拟机运行错误处理的方案
当Hyper-V中的Windows 10虚拟机出现运行错误时,可按以下步骤处理:首先进行基本检查与修复,包括检查虚拟机配置、确保Hyper-V服务正常运行及重启相关服务。其次,使用PowerShell命令或DISM工具修复虚拟机配置和系统组件。接着,查看事件查看器中的错误日志,分析问题原因。调整虚拟机资源分配,优化性能。针对特定错误情况,如启动失败或网络问题,采取相应措施解决。若问题仍未解决,考虑克隆、重置或重新安装虚拟机,必要时联系技术支持。操作前请备份重要数据并以管理员身份运行命令。
|
6月前
|
存储 Java C++
JVM 运行时数据区
Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存区域划分为若干个不同的数据区域。这 些区域都有各自的用途,以及创建和销毁的时间,有些区域随着虚拟机进程的启动而存在,有些区 域则是依赖线程的启动和结束而建立和销毁。Java 虚拟机所管理的内存被划分为如下几个区域 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解 析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳 转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成; 为什么要线程计数器?因为线程是不具备记忆功能 Java 虚拟机
|
9月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
|
9月前
|
Java
JVM运行时数据区
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一
113 2
|
10月前
|
Java
JVM运行时数据区(内存结构)
1)虚拟机栈:每次调用方法都会在虚拟机栈中产生一个栈帧,每个栈帧中都有方法的参数、局部变量、方法出口等信息,方法执行完毕后释放栈帧 (2)本地方法栈:为native修饰的本地方法提供的空间,在HotSpot中与虚拟机合二为一 (3)程序计数器:保存指令执行的地址,方便线程切回后能继续执行代码
133 3
|
11月前
|
存储 Dart Java
Dart 虚拟机运行原理
【10月更文挑战第20天】Dart 虚拟机通过一系列复杂的机制和操作,确保 Dart 代码能够准确、高效地执行。它为 Dart 语言的广泛应用提供了坚实的基础和可靠的运行环境
277 6
|
11月前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。