【JVM】运行时数据区、程序计数器


🐌个人主页: 🐌 叶落闲庭

💨我的专栏:💨
c语言
数据结构
javaEE
操作系统
Redis

石可破也,而不可夺坚;丹可磨也,而不可夺赤。


JVM

  • [一、 运行时数据区](#一、 运行时数据区)
  • [二、 程序计数器](#二、 程序计数器)

类加载器将字节码文件加载到内存当中的时候,会用到两块内存区域:一块是方法区、另外一块叫做堆区,这两块区域都属于Java虚拟机管理的内存,由于JVN在运行过程中会去使用这块内存,所以就称之为运行时数据区域,它的职责除了保存字节码信息之外,还可以将创建出来的对象放到这块内存区域。

一、 运行时数据区

通常把运行时数据区换分为两类,一类是线程不共享(程序计数器、Java虚拟机栈、本地方法栈)、一类是线程共享(方法区、堆区)

  • 线程不共享指的是每当创建一个线程之后,每个线程里都会有一份程序计数器、Java虚拟机栈和本地方法栈对应的数据,该数据由本线程维护,其他线程无法访问本线程对应的数据,所以数据无法做到共享,但是整体安全性比较高,当线程结束后,将整个线程回收掉,这块内存区域也会得到释放。
  • 线程共享指的是只要往方法区/堆区放入数据,每个线程都可以获取这些数据并去使用,虽然数据可以共享,但是存在安全性问题

二、 程序计数器

程序计数器(Program Counter Register)也叫PC寄存器,每个线程会通过程序计数器记录当前要执行的的字节码指令的地址。

  • 属于线程独自拥有的数据,里面存放了接下来要执行的字节码指令的内存地址。
  • 字节码指令最初是保存在字节码文件中的,类加载器把字节码文件读取到内存之后,这个指令也会保存到内存当中,每一行指令都有对应的内存地址。
  • 字节码指令最终是要被解释器解释执行的,所以解释器就需要知道要执行的字节码指令在哪,而程序计数器就恰恰保存了字节码指令的地址,解释器只需要通过程序计数器就能得到字节码指令的内存地址。

程序计数器的案例

  • 源代码
java 复制代码
public static void main(String[] args) {
        int i = 0;
        if (i == 0) {
            i--;
        }
        i++;
    }
  • 字节码指令
Java 复制代码
0 iconst_0
1 istore_1
2 iload_1
3 ifne 9 (+6)
6 iinc 1 by -1
9 iinc 1 by 1
12 return

将局部变量 i 赋值为0

  • iconst_0
  • istore_1

判断 i 和0是否相等,如果不相等,跳转到指令9的位置

  • iload_1
  • ifne 9 (+6)

i 和 0 相等,就将i减1:

  • iinc 1 by -1

i 和 0 不相等,就将 i 加1:

  • iinc 1 by 1

接下来这个字节码指令就会进入类的加载阶段被加载到内存中,原来字节码指令的每条指令前都有一个偏移量,加载到内存后,偏移量会被替换成地址,每一条字节码指令都会有自己的内存地址,在代码执行过程中,程序计数器会记录下一行字节码指令的地址。执行完当前指令之后,虚拟机的执行引擎根据程序计数器执行下一行指令。
程序计数器可以控制程序指令的进行,实现分支、跳转、异常等逻辑。
在多线程执行情况下,Jva虚拟机需要通过程序计数器记录CPU切换前解释执行到那一句指令并继续解释运行。


相关推荐
stillaliveQEJ31 分钟前
【JVM】基础概念之为什么要使用JVM
jvm
维诺菌4 小时前
k8s java应用pod内存占用过高问题排查
java·jvm·云原生·容器·性能优化·kubernetes
007php0076 小时前
百度面试题解析:synchronized、volatile、JMM内存模型、JVM运行时区域及堆和方法区(三)
java·开发语言·jvm·缓存·面试·golang·php
智海观潮7 小时前
JVM垃圾回收器、内存分配与回收策略
java·大数据·jvm
小杰帅气1 天前
内存管理C++
jvm
YuanlongWang1 天前
C#基础——GC(垃圾回收)的工作流程与优化策略
java·jvm·c#
白露与泡影1 天前
BAT 大厂 java高频面试题汇总:JVM+Spring+ 分布式 +tomcat+MyBatis
java·jvm·spring
それども1 天前
忽略Lombok构建警告
java·开发语言·jvm
专注于大数据技术栈1 天前
Java中JDK、JRE、JVM概念
java·开发语言·jvm
YuanlongWang1 天前
C# 基础——值类型与引用类型的本质区别
java·jvm·c#