icode icode
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

iqqcode

保持对技术的探索实践与热爱
首页
  • Android学习

    • 📁基础内容
    • 📺AndroidCore
    • 🎨Android-UI
    • 🏖️Components
    • 📊Fragment
    • 🔗网络操作
    • 🔏异步机制
    • 📦数据存储
    • 🗃️Gradle
  • 学习笔记

    • 『框架』笔记
    • 『Kotlin』笔记
    • 《Vue》笔记
    • 《Git》学习笔记
    • 『Bug踩坑记录』
  • ListView
  • RecyclerView
  • ViewPager
  • Java笔记

    • 🟠JavaSE
    • 🟢JavaWeb
    • 🔴JavaEE
    • ⚪JavaTopic
    • 🍳设计模式
  • 计算机基础

    • 📌计算机网络
    • 🔍数据结构
    • 📦数据库
    • 💻OS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
  • 关于

    • 📫关于我
  • 收藏

    • 网站
    • 资源
    • Vue资源
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaSE

    • 面向对象

    • 常用API

    • 集合类

    • 多线程

    • JDK8新特性

    • IO流

    • JVM

      • 类加载系统
      • 运行时数据区及线程
      • 程序计数器
        • 1. 程序计数器
          • 线程私有
          • 不会产生OOM
        • 2. 程序计数器的使用
        • 3. 面试题考点
      • 虚拟机栈
      • 本地方法栈
      • 堆
      • 方法区
      • 对象实例化的内存布局与访问定位
      • 面试考点
      • 垃圾回收算法
      • 执行引擎
      • 垃圾回收相关概念
      • 垃圾回收算法
      • 垃圾回收器
      • GC日志分析
      • JVM内存区域与内存溢出异常
      • JVM垃圾回收器与内存分配策略
      • Java内存模型JMM详解
      • StringTable详解
      • 站在虚拟机栈的角度,用字节码来理解i++和++i
  • JavaWeb

  • JavaEE

  • JavaTopic

  • 设计模式

  • 计算机基础

  • Java后端
  • JavaSE
  • JVM
iqqcode
2021-06-17
目录

程序计数器

# 1. 程序计数器

程序计数器(Program Counter Register,也称作PC计数器)是一块很小的内存空间,可以当做是当前线程所执行字节码的行号指示器。JVM中的程序计数器是对物理PC寄存器的模拟抽象。

【程序计数器的作用】

执行引擎的解释器在工作时就是通过改变程序计数器来选取下一条需要执行的字节码指令

程序控制流的指示器,分支、循环、跳转异常处理、线程恢复等基础功能都需要依赖程序计数器完成。

大白话来讲,就是执行引擎解释执行字节码文件,在执行完当前行的字节码时,PC计数器会告诉执行引擎下一行在什么位置,该执行谁了。

PC计数器存储的是下一条指令的地址

# 线程私有

我们都知道,Java虚拟机的多线程实现是通过CPU分配执行时间来对线程轮流切换执行的,也就是说在同一时刻,一个处理器只会执行一个线程中的指令。

PC计数器存储的当前线程指令的地址,所以它是线程私有的,每个线程都会有自己的PC计数器。生命周期与线程的生命周期保持一致。

执行本地方法时,由于是C/C++的代码,PC计数器无法记录,则是未指定值(Undefined)

# 不会产生OOM

PC计数器相对于运行时数据区的其他区域来说,所占的空间很小,存放的都是地址,不会被垃圾回收

PC计数器是Runtime Data Area中唯一不会产生OOM(内存溢出)的区域

# 2. 程序计数器的使用

我们对一段简单的程序进行测试,来验证PC计数器的内容:

Ctrl + Shift + F9编译

编译后的字节码class

package iqqcode.pcregister;

public class PCRegisterTest {
    public PCRegisterTest() {
    }

    public static void main(String[] args) {
        int i = 10;
        int j = 20;
        int var10000 = i + j;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

对字节码进行反编译

javap -v PCRegisterTest.class

在虚拟机字节码指令的左侧,就是PC计数器中存放的指令的偏移地址

# 3. 面试题考点

Q1:为什么使用PC寄存器记录当前线程的执行地址呢?

或者说使用PC寄存器存储字节码指令地址有什么用呢?

答:记录线程的上下文环境。 当线程进行上下文切换(Context Switch)发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态。Java中对应的概念就是程序计数器,它的作用是记住下一条JVM指令的执行地址,是线程私有的。


其实这个问题我们可以类比CPU的中断处理过程,CPU在响应中断之前,为了在中断处理结束后能正确地返回到中断点,会先记录当前执行位置,即保护现场、保护断点,它将断点放到了程序计数器中。


我们类比操作系统中CPU的响应中断机制来说明:

CPU要轮番切换各个线程来调度执行,在切换当前线程之前,需要记录当前的执行位置(理解为线程的中断点)。在下次切换回当前线程后,知道接着从哪里继续执行(避免重头再执行)

JVM的执行引擎----字节码解释器通过改变PC计数器的值来明确下一条要执行的指令。


Q2:PC寄存器为什么会被设定为线程私有?

我们都知道,Java虚拟机的多线程实现是通过CPU分配执行时间来对线程轮流切换执行的,也就是说:在同一时刻,一个处理器只会执行一个线程中的指令。

PC计数器存储当前线程指令的地址,为了保证能够准确地记录各个线程正在执行的当前字节码指令的地址,所以它是线程私有的,每个线程都会有自己的PC计数器。

编辑 (opens new window)
上次更新: 2021/06/27, 10:49:09
运行时数据区及线程
虚拟机栈

← 运行时数据区及线程 虚拟机栈→

最近更新
01
匿名内部类
10-08
02
函数式接口
10-08
03
ARouter-Kotlin踩坑
10-05
更多文章>
Theme by Vdoing | Copyright © 2021-2023 iqqcode | MIT License | 备案号-京ICP备2021028793号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×