Java虚拟机 - 程序计数器和虚拟机栈

运行时数据结构

  • Java运行时数据区
    • 程序计数器
    • 为什么需要程序计数器
    • 执行流程
    • 虚拟机栈
      • 虚拟机栈作用
      • 虚拟机栈核心结构
      • 运行机制

Java运行时数据区

首先介绍Java运行时数据之前,我们要了解,对于计算机来说,内存是非常重要的资源,因为内存是连接CPU与硬盘的桥梁,承载着操作系统与应用程序的运行的基础。JVM在运行期间把它管理的内存分为若干个区域,有些区域是线程私有的,有些区域是共享的。
Java运行时数据区作为JVM在程序执行过程中管理内存的核心结构,主要包括方法区(存储类元数据、运行时常量池、静态变量)、堆(存放对象实例和数组,被所有线程共享且是垃圾回收的主区域)、虚拟机栈(每个线程私有,用于存储方法调用的栈帧,包含局部变量表、操作数栈及方法出口)、本地方法栈(支持Native方法调用)和程序计数器(记录当前线程执行的字节码位置,确保多线程切换后能恢复执行)。其中,堆和方法区是线程共享的,而虚拟机栈、本地方法栈和程序计数器为线程私有,共同协作实现Java程序的内存分配、方法执行及多线程调度。
在这里插入图片描述

程序计数器

程序计数器(Program Counter Register)在JVM中可以当成当前线程所执行的字节码的行号指示器,在JVM的概念模型里面,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器。分支 、循环 、跳转 、异常处理 、线程恢复等都是依赖这个计数器来实现的。
在这里插入图片描述
如果程序执行的是Java方法,计数器代表的是只在执行的虚拟机字节码的地址;如果执行的是本地方法,这个计数器的值为空(undefined)。此外,这个计数器区域是Java虚拟机规范的没有规定任何内存溢出的地方,程序计数区既没有内存溢出,也没有垃圾回收。因为程序计数器是很小的一块内存区域,几乎可以忽略不记,同时也是运行最快的区域。

为什么需要程序计数器

因为CPU需要不停的切换各个线程,做完切换之后,需要知道接下来从哪里开始执行。通过使用程序计数器保存了接下来要执行的地址,这样CPU切换过来之后就可以直接接着执行。

执行流程

// 示例代码
public class Demo {public int test() {int a = 10;int b = 20;int c = a + b;String d = "abd";System.out.println(d);return d.length();}
}

通过javap -c Demo.class反编译后:

 0 bipush 102 istore_13 bipush 205 istore_26 iload_17 iload_28 iadd9 istore_3
10 ldc #2 <abd>
12 astore 4
14 getstatic #9 <java/lang/System.out : Ljava/io/PrintStream;>
17 aload 4
19 invokevirtual #15 <java/io/PrintStream.println : (Ljava/lang/String;)V>
22 aload 4
24 invokevirtual #21 <java/lang/String.length : ()I>
27 ireturn

在这里插入图片描述

虚拟机栈

虚拟机栈(Java Virtual Machine Stack)是JVM内存模型中与线程执行密切相关的核心区域,用于存储方法调用的栈帧(Stack Frame)。它是线程私有的内存空间,每个线程在创建时都会分配一个独立的虚拟机栈,其生命周期与线程一致。以下从设计目标、核心结构、运行机制到常见问题全面解析。

虚拟机栈作用

虚拟机栈的核心功能是支持Java方法的调用与执行,具体包括:

  • 方法调用链管理:保存方法的调用顺序(如 main() → methodA() → methodB())。

  • 局部变量存储:存储方法内的基本类型变量、对象引用。

  • 操作数计算:提供临时数据存储空间(如算术运算的中间结果)。

  • 方法返回控制:记录方法执行完成后的返回地址。

虚拟机栈核心结构

虚拟机栈由多个栈帧(Stack Frame)构成,每个栈帧对应一个方法的调用。栈帧包含以下核心部分:

  1. 局部变量表(Local Variables Table)
    作用:存储方法参数和方法内定义的局部变量。

     结构:以变量槽(Slot)为最小单位,每个Slot占用32位(long和double占2个Slot)。索引从0开始,依次存放this(非静态方法)、方法参数、局部变量。示例:
    
public void demo(int a, String b) {double c = 3.14;Object d = new Object();
}
局部变量表结构:

在这里插入图片描述

  1. 操作数栈(Operand Stack)

    作用:保存计算过程中的临时数据(类似CPU的寄存器)。

    特点:

     深度在编译期确定(写入方法表的max_stack属性)。通过iconst_1、iadd等字节码指令操作栈顶元素。
    
int result = 1 + 2;
iconst_1  // 压入1
iconst_2  // 压入2
iadd      // 弹出1和2,相加后压入3
istore_1  // 将3存储到局部变量表索引1
  1. 动态链接(Dynamic Linking)
  • 作用:将符号引用(如com/example/Demo.methodA)转换为直接引用(内存地址)。

  • 意义:支持多态特性(如接口方法、虚方法调用)。

  • 对比:

    • 静态解析:类加载阶段可确定的直接引用(如final方法)。

    • 动态链接:运行时才能确定(如重写方法)。

  1. 方法返回地址(Return Address)
    作用:记录方法正常结束或异常退出后的返回位置。
    两种返回方式:
  • 正常返回(return指令):程序计数器恢复为调用者的下一条指令地址。

  • 异常退出:通过异常处理器表(Exception Table)确定跳转地址。

运行机制

  1. 方法调用与栈帧压栈
    调用方法时:创建新栈帧并压入栈顶。

方法返回时:栈帧弹出,释放内存。

  1. 栈溢出(StackOverflowError)
    触发条件:线程请求的栈深度超过JVM允许的最大值(如无限递归)。

示例:

public class StackOverflowDemo {public static void main(String[] args) {infiniteCall(); // 无限递归调用}static void infiniteCall() {infiniteCall();}
}

报错信息:

Exception in thread "main" java.lang.StackOverflowError
  1. 栈大小配置
    参数:-Xss(如-Xss1m设置栈大小为1MB)。

默认值:不同JVM实现不同(HotSpot Linux x64默认1MB)。

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

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

相关文章

MySQL数据库——支持远程IP访问的设置方法总结

【系列专栏】&#xff1a;博主结合工作实践输出的&#xff0c;解决实际问题的专栏&#xff0c;朋友们看过来&#xff01; 《项目案例分享》 《极客DIY开源分享》 《嵌入式通用开发实战》 《C语言开发基础总结》 《从0到1学习嵌入式Linux开发》 《QT开发实战》 《Android开发实…

CSS- 4.6 radiu、shadow、animation动画

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在HBuilder中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查看&#xff01; 点…

排序算法之基础排序:冒泡,选择,插入排序详解

排序算法之基础排序&#xff1a;冒泡、选择、插入排序详解 前言一、冒泡排序&#xff08;Bubble Sort&#xff09;1.1 算法原理1.2 代码实现&#xff08;Python&#xff09;1.3 性能分析 二、选择排序&#xff08;Selection Sort&#xff09;2.1 算法原理2.2 代码实现&#xff…

第十节第一部分:常见的API:Math、System、Runtime

Math类介绍及常用方法&#xff08;了解知道即可&#xff09; System类介绍及常用方法&#xff08;了解知道即可&#xff09; Runtime类介绍及常用方法&#xff08;了解知道即可&#xff09; 代码&#xff1a; 代码一&#xff1a;Math类 package com.itheima.d14_math;public …

智能体间协作的“巴别塔困境“如何破解?解读Agent通信4大协议:MCP/ACP/A2A/ANP

AI 智能体的兴起触发了AI应用协作的新领域。这些智能体不再局限于被动的聊天机器人或独立的系统&#xff0c;它们现在被设计用于推理、计划和协作ーー跨任务、跨域甚至跨组织。但随着这一愿景成为现实&#xff0c;一个挑战很快浮出水面&#xff1a; 智能体如何以一种安全、可伸…

项目进度延误,如何按时交付?

项目进度延误可以通过加强计划管理、优化资源分配、强化团队沟通、设置关键里程碑和风险管理机制等方式来实现按时交付。加强计划管理、优化资源分配、强化团队沟通、设置关键里程碑、风险管理机制。其中&#xff0c;加强计划管理尤为关键&#xff0c;因为明确而详细的计划能提…

详解ip地址、子网掩码、网关、广播地址

1. IP 地址 定义&#xff1a;IP 地址是网络设备在网络中的唯一标识&#xff0c;用于标识设备的网络位置&#xff0c;类似于现实中的门牌号。它分为 IPv4&#xff08;如 192.168.1.5&#xff09;和 IPv6&#xff08;如 240e:305:3685:8100:a00:27ff:fefb:56b8&#xff09;。 示…

为 Windows 和 Ubuntu 中设定代理服务器的详细方法

有时下载大模型总是下载不出来&#xff0c;要配置代理才行 一、Windows代理设置 ① 系统全局代理设置 打开【设置】→【网络和Internet】→【代理】。 在【手动设置代理】下&#xff0c;打开开关&#xff0c;输入&#xff1a; 地址&#xff1a;10.10.10.215 端口&#xff1a;…

鸿蒙OSUniApp 实现的表单验证与提交功能#三方框架 #Uniapp

UniApp 实现的表单验证与提交功能 前言 在移动端应用开发中&#xff0c;表单是用户与应用交互的重要媒介。一个好的表单不仅布局合理、使用方便&#xff0c;还应该具备完善的验证与提交功能&#xff0c;以确保用户输入的数据准确无误。本文将分享如何在 UniApp 中实现表单验证…

前端的面试笔记——HTMLJavaScript篇(二)前端页面性能检测

前端页面性能检测和判定是优化用户体验的核心环节&#xff0c;需要结合实验室数据&#xff08;Lab Data&#xff09;、现场数据&#xff08;Field Data&#xff09;和行业标准综合评估。以下是主流方法、工具及判定标准的详细解析&#xff1a; 一、性能检测的核心维度与指标 …

再来1章linux系列-19 防火墙 iptables 双网卡主机的内核 firewall-cmd firewalld的高级规则

学习目标&#xff1a; 实验实验需求实验配置内容和分析 &#xff08;每一个设备的每一步操作&#xff09;实验结果验证其他 学习内容&#xff1a; 实验实验需求实验配置内容和分析 &#xff08;每一个设备的每一步操作&#xff09;实验结果验证其他 1.实验 2.实验需求 图…

LLM-Based Agent综述及其框架学习(五)

文章目录 摘要Abstract1. 引言2. 文本输出3. 工具的使用3.1 理解工具3.2 学会使用工具3.3 制作自给自足的工具3.4 工具可以扩展LLM-Based Agent的行动空间3.5 总结 4. 具身动作5. 学习智能体框架5.1 CrewAI学习进度5.2 LangGraph学习进度5.3 MCP学习进度 参考总结 摘要 本文围绕…

游戏引擎学习第298天:改进排序键 - 第1部分

关于向玩家展示多个房间层所需的两种 Z 值 我们在前一天基本完成了为渲染系统引入分层 Z 值的工作&#xff0c;但还没有完全完成所有细节。我们开始引入图形渲染中的分层概念&#xff0c;即在 Z 轴方向上拥有多个独立图层&#xff0c;每个图层内部再使用一个单独的 Z 值来实现…

一些C++入门基础

关键字 图引自 C 关键词 - cppreference.com 命名空间 命名空间解决了C没办法解决的各类命名冲突问题 C的标准命名空间&#xff1a;std 命名空间中可以定义变量、函数、类型&#xff1a; namespace CS {//变量char cs408[] "DS,OS,JW,JZ";int cs 408;//函数vo…

学习笔记:黑马程序员JavaWeb开发教程(2025.4.6)

12.4 登录校验-JWT令牌-介绍 JWT&#xff08;JSON Web Token&#xff09; 简洁是指JWT是一个简单字符串&#xff0c;自包含指的是JWT令牌&#xff0c;看似是一个随机字符串&#xff0c;但是可以根据需要&#xff0c;自定义存储内容 Header是JSON数据格式&#xff0c;原始JSO…

香港科技大学物理学理学(科学计算与先进材料物理与技术)硕士招生宣讲会——深圳大学

香港科技大学物理学理学&#xff08;科学计算与先进材料物理与技术&#xff09;硕士招生宣讲会——深圳大学专场 &#x1f559;时间&#xff1a;2025年5月23日&#xff08;星期五&#xff09;14:30 &#x1f3eb;地点&#xff1a;深圳大学沧海校区致原楼1101 &#x1f9d1…

数据库优化技巧:MySQL 重复数据查询与删除(仅保留一条)的性能优化策略

目录 一、查询重复数据 二、删除重复数据 方法 1&#xff1a;创建临时表&#xff0c;操作完成后再删除临时表&#xff08;安全可靠&#xff0c;适合大表&#xff09; 步骤 1&#xff1a;创建临时表存储需删除的 ID 步骤 2&#xff1a;根据临时表删除数据 方法 2&#xff1a…

分布式ID生成器:原理、对比与WorkerID实战

一、为什么需要分布式ID&#xff1f; 在微服务架构下&#xff0c;单机自增ID无法满足跨服务唯一性需求&#xff0c;且存在&#xff1a; • 单点瓶颈&#xff1a;数据库自增ID依赖单表写入 • 全局唯一性&#xff1a;跨服务生成可能重复 • 扩展性差&#xff1a;分库分表后ID规…

Golang的代码注释规范与实践

# Golang的代码注释规范与实践 一、注释的重要性 代码注释是程序员交流的桥梁 代码注释是程序员之间沟通交流的重要形式&#xff0c;良好的注释能够帮助其他开发者更快地理解代码的意图和实现方式。 代码维护离不开注释 在项目维护过程中&#xff0c;良好的注释能够帮助开发者回…

Qt读取Excel文件的技术实现与最佳实践

目录 一、成果展示二、核心方法及原理1. QAxObject(基于COM接口)2. 第三方库QXlsx3. ODBC数据库驱动三、实现步骤详解1. QAxObject读取Excel(需安装Excel/WPS)2. QXlsx读取Excel(跨平台方案)四、技术选型与对比五、应用场景与优化建议1. 高频数据处理2. 跨平台工具开发3.…