JVM工作原理与实战(十六):运行时数据区-Java虚拟机栈

专栏导航

JVM工作原理与实战

RabbitMQ入门指南

从零开始了解大数据


目录

专栏导航

前言

一、运行时数据区

二、Java虚拟机栈

1.栈帧的组成

2.局部变量表

3.操作数栈

4.帧数据

总结


前言

JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容。 ​


一、运行时数据区

Java虚拟机(JVM)在运行Java程序期间,会创建并维护一系列内存区域,这些区域总称为运行时数据区。这些区域根据其用途和特性,被严格定义并管理。《Java虚拟机规范》详细规定了这些区域的作用和行为,以确保所有Java虚拟机实现的一致性和正确性。

线程不共享区域:

  • 程序计数器:用于存储当前线程执行的字节码指令地址。这个区域是每个线程独有的,不共享。
  • Java虚拟机栈:每个线程在创建时都会创建一个虚拟机栈,每个方法调用都会创建一个栈帧,用于存储局部变量、操作数栈、动态链接和方法出口信息。
  • 本地方法栈:与虚拟机栈相似,本地方法栈为native方法提供服务。

线程共享区域:

  • 方法区:用于存储已被JVM加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。
  • :堆是所有线程共享的区域,用于动态分配内存。所有的对象实例以及数组都应当在堆上分配。

二、Java虚拟机栈

Java虚拟机栈是Java技术中至关重要的部分,它负责管理方法调用中的基本数据。在执行Java程序时,Java虚拟机栈是线程私有的,即每个线程都拥有自己的Java虚拟机栈,并且随着线程的创建而创建,随着线程的销毁而回收。

Java虚拟机栈,运用栈式数据结构对方法调用过程中的基本数据进行管理。遵循先进后出(First In Last Out)的原则,每一个方法调用都会对应一个独立的栈帧(Stack Frame)进行数据存储。

1.栈帧的组成

Java虚拟机栈的核心组成部分是栈帧,每一个方法的调用都会对应一个栈帧。这个栈帧存储了该方法的所有信息,包括局部变量、操作数栈、动态链接、方法出口等。

  • 局部变量表:这是在运行过程中存放所有局部变量(包括方法参数)的区域。在编译成字节码文件时,就可以确定局部变量表的内容。每个槽(slot)可以存放一个值,如果该值为long或double类型,则该槽会占用两个槽的空间。此外,实例方法的局部变量表中序号为0的位置存放的是this指针,它指向当前调用方法的对象。
  • 操作数栈:这是执行指令时存放临时数据的区域。操作数栈是实现中间计算结果交换和保存的主要场所,同时它也是函数调用的主要数据交互通道。函数作为参数传递时,就将其放在操作数栈上传递。
  • 帧数据:这部分主要包含动态链接、方法出口、异常表的引用等。动态链接保存了符号引用与运行时常量池的内存地址的映射关系。方法出口则指出了方法正常或异常结束时,当前栈帧应如何被弹出。异常表则是用于处理代码中异常的信息,包含了异常捕获的生效范围以及异常发生后跳转到的字节码指令位置。

2.局部变量表

局部变量表是存储在栈帧中的一块区域,它的作用是在方法执行过程中存放所有的局部变量。这些变量在编译成字节码文件时就可以确定其内容。

案例:

public class Demo1 {public static void test() {int i = 0;long j = 1;}
}

字节码:

0 iconst_0
1 istore_0
2 lconst_1
3 lstore_1
4 return

局部变量表(Nr.表示编号;起始PC、长度表示生效范围):

案例分析图:

栈帧中的局部变量表是一个数组,数组中的每个位置称之为槽(slot)。每个槽可以存放一个值,long和double类型的数据会占用两个槽的空间,其他类型的数据则占用一个槽。

局部变量表(序号表示槽的起始编号):

在实例方法中,序号为0的位置专门用于存储当前调用方法的对象引用,即this指针。在运行时,该位置将存储实例对象的内存地址,以便于访问和操作对象的属性和方法。 

案例:

public class Demo1 {public void test() {int i = 0;long j = 1;}
}

局部变量表:

方法参数也会保存在局部变量表中,其顺序与方法中参数定义的顺序一致。 

局部变量表保存的内容有:实例方法的this对象、方法的参数、方法体中声明的局部变量等。为了节省空间,局部变量表中的槽是可以复用的,一旦某个局部变量不再生效,当前槽就可以再次被使用。

案例:

public class Demo1 {public void test(int x,int y) {int i = 0;long j = 1;}
}

局部变量表:

3.操作数栈

操作数栈是栈帧中虚拟机在执行指令过程中用来存放临时数据的一块区域。它是一种栈式的数据结构,如果一条指令将一个值压入操作数栈,则后面的指令可以弹出并使用该值。在编译期就可以确定操作数栈的最大深度,从而在执行时正确地分配内存大小。

案例:

public class Demo1 {public void test() {int i = 0;int j = i + 1;}
}

字节码文件信息:

字节码:

0 iconst_0
1 istore_1
2 iload_1
3 iconst_1
4 iadd
5 istore_2
6 return

字节码分析:

0 iconst_0将常量0放入操作数栈
1 istore_1从操作数栈取出放入局部变量表1号位置
2 iload_1将局部变量表1中的数据放入操作数栈
3 iconst_1将常量1放入操作数栈
4 iadd将操作数栈顶部的两个数据进行累加,结果放入栈中
5 istore_2从操作数栈取出放入局部变量表2号位置
6 return方法结束,返回

4.帧数据

当当前类的字节码指令引用了其他类的属性或方法时,需要将符号引用(编号)转换成对应的运行时常量池中的内存地址。动态链接就保存了编号到运行时常量池的内存地址的映射关系。这样在执行时就可以快速地找到对应的内存地址。

方法出口指的是方法在正确或异常结束时,当前栈帧会被弹出,同时程序计数器应该指向上一个栈帧中的下一条指令的地址。所以在当前栈帧中,需要存储此方法出口的地址。这样在方法结束时,就可以快速地返回到上一个方法的执行位置。

异常表主要用于存储代码中异常的处理信息,它不仅涵盖了异常捕获的有效范围,还包含了try代码块和catch代码块执行后的字节码指令跳转位置。通过异常表,虚拟机能够精确地定位异常发生的位置,并采取适当的处理措施,从而确保程序的稳定性和可靠性。

案例:

public class Demo1 {public void test() {try {int i = 0;} catch (Exception e) {int j = 1;} finally {int k = 2;}}
}

字节码文件信息:

字节码:

 0 iconst_01 istore_12 iconst_23 istore_14 goto 21 (+17)7 astore_18 iconst_19 istore_2
10 iconst_2
11 istore_1
12 goto 21 (+9)
15 astore_3
16 iconst_2
17 istore 4
19 aload_3
20 athrow
21 return


总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了运行时数据区、Java虚拟机栈等内容,希望对大家有所帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/415221.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年美国各州即将生效的新隐私保护法(上)

2024年美国各州即将生效的新隐私保护法(上) 文章目录 2024年美国各州即将生效的新隐私保护法(上)前言一、2023年隐私保护法开始生效的五个州二、2023年通过了新的隐私保护法的八个州三、2024年确定截止的州及法律法规(…

leetcode234. 回文链表

题目 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2: 输入:hea…

竞赛保研 大数据疫情分析及可视化系统

文章目录 0 前言2 开发简介3 数据集4 实现技术4.1 系统架构4.2 开发环境4.3 疫情地图4.3.1 填充图(Choropleth maps)4.3.2 气泡图 4.4 全国疫情实时追踪4.6 其他页面 5 关键代码最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 大数据疫…

学习k8s的应用(三)

一、k8s部署ngnix 1、一些查看命令 1-1、所有命令空间 kubectl get pod --all-namespaces kubectl get svc --all-namespaces1-2、指定命令空间 kubectl get pod -n yabin kubectl get svc -n yabin2、单节点集群兼容 # 因为目前只有一个master节点,默认安装后…

Java 方法(方法的调用机制、方法的传参机制)

方法 方法就是将一个功能抽取出来,把代码单独定义在一个大括号内,形成一个单独的功能。 当需要这个功能的时候,就可以去调用。这样即实现了代码的复用性,也解决了代码冗余的现象。 修饰符 返回值类型 方法名 (参数列…

C练习——杨辉三角

题目: 打印近似杨辉三角,行数n自选 百度找的杨辉三角,参考一下: 解析: 把它的全部元素左对齐,就可以看成近似杨辉三角的样子 1 1 1 1 2 1 1 3 3 1 1 4 6 4 1 …… 每个数等于它上方两数…

excel(vab)删除空行

删除第一、二、三列位空的所有行(8000)行范围以内 代码如下: Sub Macro1()Dim hang As Integer For hang 8000 To 1 Step -1If Sheet1.Cells(hang, 1) "" And Sheet1.Cells(hang, 2) "" And Sheet1.Cells(hang, 3) "&quo…

怎么处理vue项目中的错误详解

文章目录 一、错误类型二、如何处理后端接口错误代码逻辑问题全局设置错误处理生命周期钩子 三、源码分析小结参考文献 一、错误类型 任何一个框架,对于错误的处理都是一种必备的能力 在 Vue 中,则是定义了一套对应的错误处理规则给到使用者&#xff0…

C++ 设计模式之 中介者模式

【声明】本题目来源于卡码网(题目页面 (kamacoder.com)) 【提示:如果不想看文字介绍,可以直接跳转到C编码部分】 【设计模式大纲】 【简介】 -- 什么是中介者模式 (第16种模式) 中介者模式(Medi…

如何在 Element Plus 中使用自定义 icon 组件 (非组件库内置icon)

先说原理就是将 svg 文件以 vue 组件文件的方式使用 需求:我想要在 Element Plus 得评分组件中使用自定义得图标。 el-rate v-model"value1" /> 组件本身是支持自定义图标的,但是教程中只说明了如何使用 element-plus/icons-vue 图标库内置…

TortoiseSVN客户端如何安装配置并实现公网访问服务端提交文件到本地服务器

文章目录 前言1. TortoiseSVN 客户端下载安装2. 创建检出文件夹3. 创建与提交文件4. 公网访问测试 前言 TortoiseSVN是一个开源的版本控制系统,它与Apache Subversion(SVN)集成在一起,提供了一个用户友好的界面,方便用…

vue写了debugger谷歌浏览器打开控制台没进断点

vue代码中打了断点,谷歌打开f12进不了断点解决方案如下 1、打开谷歌浏览器控制台,点击设置 2、在 Ignore List 中将“Enable Ignore Listing”勾选去掉,然后就可以正常使用debugger了