【JVM系列】字节码执行到哪儿了?——说说JVM程序计数器

【JVM系列】字节码执行到哪儿了?------说说JVM程序计数器

欢迎关注,​分享更多原创技术内容~

微信公众号:ByteRaccoon、知乎:一只大狸花啊、稀土掘金:浣熊say

微信公众号海量Java、数字孪生、工业互联网电子书免费送~

什么是程序计数器?

JVM读书的指头------程序计数器

如果我们把字节码文件看作一本书的话,那么JVM的活儿其实很简单。就是照着字节码文件这本书一句一句去读,然后翻译给我们的CPU去执行。所以说JVM也有点儿像一个传达命令的翻译官,将Java源代码文件编译成的字节码文件翻译成各个硬件平台的指令,然后让计算机运行。

那么,不妨想想我们在读书的时候需要干些什么事情,需要有个桌子,草稿纸,书以及人。桌子就好比是计算机内存,Java字节码这本书只能放在内存里,为了提高读书效率,JVM还贴心的将内存分为堆、程序计数器、虚拟机栈、方法区和程序计数器。这些内存区域各有各的作用,但是我们今天重点需要介绍的是------程序计数器。

我们平时读书的时候习惯用手指着书,知道书读到哪一行了,有时候我们可能中途离开干其它事情、读其它书可能会有一个书签,记录当前读到的位置。JVM比我们更聪明一点儿,单独分配了一块儿内存区域叫做程序计数器,来充当手指作用的同时还能在上面记录下当前执行到的JVM 字节码的位置。这样以来在干完其它事的时候,能快速的从上次读过的地方继续开始。

这就是我们说的程序计数器的作用------记录字节码文件的执行位置。

正经说说什么是程序计数器

程序计数器也叫做程序寄存器(Program Counter Register),虽然它在JVM中是一块内存区域,但是其作用更类似于指令寄存器的作用,即会存储JVM需要执行的下一条指令。

在JVM中,程序计数器是线程私有的,每个线程都有自己独立的程序计数器,其生命周期与线程的生命周期保持一致。主要作用包括:

  1. 当前指令地址存储: 程序计数器存储的是当前线程正在执行的Java字节码指令的地址。由于Java是一种解释执行的语言,程序计数器的值被用来定位下一条即将执行的字节码指令。
  2. 线程切换时的恢复点: 程序计数器在线程切换时起到重要作用。当一个线程被挂起,另一个线程被调度执行时,JVM会通过程序计数器来恢复被挂起线程的执行状态,确保程序能够从正确的位置继续执行。
  3. 支持方法调用和返回: 在Java程序中,方法调用和返回都依赖于程序计数器。程序计数器保存方法调用的返回地址,以便方法执行完毕后能够正确返回到调用点。

程序计数器是JVM中唯一一个在多线程执行时不会发生线程安全问题的区域。这是因为每个线程有自己独立的程序计数器,不会被其他线程访问或修改。总体而言,JVM中的程序计数器在支持Java程序的运行时起到了关键的作用,它是实现线程切换和方法调用等功能的重要组成部分。

程序计数器执行流程

如上图所示,当执行Java字节码时,程序计数器(Program Counter,PC)在JVM中起着关键的作用,它负责跟踪当前线程所执行的指令地址。简单来说,程序计数器会存储处于方法区当中Java字节码的指令,表示当前执行到的指令位置。JVM引擎会根据程序计数器的地址拿到指令的物理地址,并从局部变量表和操作数栈中拿到数据进行运算。

这里来尝试分析一段简单的Java代码:

auto 复制代码
public int add(int a, int b) {
    int result = a + b;
    return result;
}

以下是上面Java代码对应的字节码文件以及其在JVM中的执行流程,强调了程序计数器在其中的作用:

java 复制代码
stack=2, locals=4, args_size=3
0: iload_1
1: iload_2
2: iadd
3: istore_3
4: iload_3
5: ireturn
  1. iload_1: 程序计数器记录下将执行的指令的地址偏移0。iload_1指令执行,将局部变量表中索引为1的局部变量(例如,整数变量 a)加载到操作数栈上。
  2. iload_2: 程序计数器更新为下一条指令的地址。iload_2指令执行,将局部变量表中索引为2的局部变量(例如,整数变量 b)加载到操作数栈上。
  3. iadd: 程序计数器继续更新。iadd指令执行,从操作数栈中弹出两个整数,相加并将结果推入操作数栈。
  4. istore_3: 程序计数器继续更新。istore_3指令执行,将操作数栈顶的整数值存储到局部变量表中索引为3的位置(例如,整数变量 result)。
  5. iload_3: 程序计数器再次更新。iload_3指令执行,将局部变量表中索引为3的局部变量的值加载到操作数栈上。
  6. ireturn: 程序计数器继续更新。ireturn指令执行,将结果作为方法的返回值,并结束方法的执行。

在整个执行过程中,程序计数器始终记录着当前线程即将执行的指令的地址。这保证了指令的有序执行,同时在方法调用、返回和异常处理等情况下,程序计数器都发挥了关键的作用。

总结

程序计数器是Java虚拟机(JVM)中的一种寄存器,负责跟踪当前线程执行的字节码指令地址。它在Java程序的执行过程中发挥着关键作用,具体功能包括记录当前指令地址、支持线程切换时的恢复点、以及管理方法调用和返回过程。

在执行Java字节码时,程序计数器通过不断更新指向下一条即将执行的指令地址,保证指令有序地执行。每个线程都有自己独立的程序计数器,确保在多线程执行时不会发生线程安全问题。程序计数器在方法调用、返回和异常处理等情况下都发挥着关键的作用,确保程序能够正确执行。总之,程序计数器是JVM中重要的组成部分,为Java程序的顺利执行提供了必要的支持。

相关推荐
哎呦没11 分钟前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
2401_8576009514 分钟前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Chrikk6 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*6 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue6 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man6 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
customer087 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源