程序计数器

  • 根据《Java虚拟机规范》的规定,运行时数据区通常包括这几个部分:程序计数器(Program Counter Register)、Java栈(VM Stack)、本地方法栈(Native Method Stack)、方法区(Method Area)、堆(Heap)。

由此先来看看程序计数器的作用。

  • 程序计数器(Program Counter Register)又叫PC寄存器,是一块很小的内存空间,也是运行速度最快的存储区域,用来存储指令向下一条指令的地址,也就是即将要执行的指令代码,由执行引擎读取下一条指令。(行号指示器)
  • 每个线程都有自己独立的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。
  • 如果线程正在执行的是一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 Native 方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。
  • 它是程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
  • 字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

例如,某段代码对应的字节码指令及对应的程序计数器的作用如下:

1
2
3
4
5
6
7
8
9
10
public class PCRegisterTest {
public static void main(String[] args) {
int i = 10;
int j = 20;
int k = i + j;
String s = "abc";
System.out.println(i);
System.out.println(k);
}
}
  • 使用PC寄存器存储字节码指令地址的作用?
    • 因为CPU需要不停地切换线程,而切换回来后,就得知道接下来需要执行的指令。字节码解释器就要通过改变这个计数器的值来选取下一条需要执行的字节码指令。
  • PC寄存器为什么会被设定为线程私有?
    • 在任意一个时刻,一个CPU内核只会执行某个线程中的一条指令,这样必然会导致线程中断或恢复,而每个线程私有的PC寄存器能够准确地记录其正在执行的当前字节码指令地址。