当前位置: 首页 > news >正文

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)。

相关文章:

  • Ubuntu 22.04安装zabbix7.0.0图形中文乱码
  • 开源CMS系统中哪些常见的安全漏洞最需要注意?
  • 微软账户无密码化的取证影响
  • XXX企业云桌面系统建设技术方案书——基于超融合架构的安全高效云办公平台设计与实施
  • [解决方案] Word转PDF
  • k8s 配置 Kafka SASL_SSL双重认证
  • 在tensorflow源码环境里,编译出独立的jni.so,避免依赖libtensorflowlite.so,从而实现apk体积最小化
  • Oracle 11g post PSU Oct18 设置ssl连接(使用wallets)
  • linux crontab定时执行python找不到module问题解决
  • 实现图片自动压缩算法,canvas压缩图片方法
  • Fiddler抓包教程->HTTP和HTTPS基础知识
  • 《算法笔记》11.4小节——动态规划专题->最长公共子序列(LCS) 问题 A: 最长公共子序列
  • [Web服务器对决] Nginx vs. Apache vs. LiteSpeed:2025年性能、功能与适用场景深度对比
  • 双指针法高效解决「移除元素」问题
  • 机器学习10-随机森林
  • [SpringBoot]Spring MVC(5.0)----留言板
  • 算法与数据结构:质数、互质判定和裴蜀定理
  • React 常见的陷阱之(如异步访问事件对象)
  • AI驱动发展——高能受邀参加华为2025广东新质生产力创新峰会
  • 榕壹云上门家政系统:基于Spring Boot+MySQL+UniApp的全能解决方案
  • 韩国第二大轮胎制造商因火灾停产,或影响700万条轮胎销售
  • 上海将完善隔代照料支持措施:建设老幼共享设施、提高科学育儿指导力度
  • 国家发改委:大部分稳就业稳经济政策将在6月底前落地
  • 再囤三个月库存!美国客户抢付尾款,外贸企业发货订单排到7月
  • C919上海虹桥-深圳航线开通,东航今年计划再接收10架C919
  • 解读|战国子弹库帛书漂泊海外79年今归国,追索仍将继续