程序计数器 笔记记录
学习资料来源-b站黑马JVM& 尚硅谷JVM精讲与GC调优
1. 定义
Program Counter Register 程序计数器
当执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。此后经过分析指令,执行指令。完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。
JVM中的程序计数寄存器(Program Counter Register)中, Register 的命名源于CPU的寄存器,寄存器存储指令相关的现场信息。 CPU只有把数据装载到寄存器才能够运行。
这里,并非是广义上所指的物理寄存器,或许将其翻译为PC计数器(或指令计数器)会更加贴切(也称为程序钩子) ,并且也不容易引起一些不必要的误会。JVM中的PC寄存器是对物理PC寄存器的一种抽象模拟。
2. 作用
可以看作是当前线程所执行的字节码的行号指示器,用于存储当前线程正在执行的 Java 方法的 JVM 指令地址。如果线程执行的是 Native 方法,计数器值为 null。是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域,生命周期与线程相同。来源于小林coding解释
3. 特点
- 线程私有,CPU给多个线程分配时间片,线程执行到某个位置的时候,可能时间片用完了,这时候就需要程序计数器去记录当前运行的指令的下一条,这样的话线程恢复后,就可以直接接着上一次执行的位置继续执行。每个线程都有自己的程序计数器。
- 唯一一个不会出现内存溢出的部分。
● 它是一块很小的内存空间,几乎可以忽略不记。也是运行速度最快的存储区域。不会随着程序的运行需要更大的空间。
● 在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。
4. 拓展理解
4.1 PC寄存器存储字节码指令地址有什么用?
使用PC寄存器存储字节码指令地址有什么用呢?
(为什么使用PC寄存器记录当前线程的执行地址呢?)
因为CPU需要不停的切换各个线程,这时候切换回来以后,就得知道接着从哪开始继续执行。
JVM的字节码解释器就需要通过改变PC寄存器的值来明确下一条应该执行什么样的字节码指令。
● 通俗解释就是,不同的线程执行是有分配的时间片的,假设A线程执行一半时间片用完了就轮到其他线程了,其他线程可能执行完了以后,A线程这时候执行肯定要依赖程序计数器的标记在哪里继续执行,总不能直接执行。
4.2 PC寄存器为什么被设定为线程私有的?
PC寄存器为什么会被设定为线程私有?
我们都知道所谓的多线程在一个特定的时间段内只会执行其中某一个线程的方法,CPU会不停地做任务切换,这样必然导致经常中断或恢复,如何保证分毫无差呢?为了能够准确地记录各个线程正在执行的当前字节码指令地址,最好的办法自然是为每一个线程都分配一个PC寄存器,这样一来各个线程之间便可以进行独立计算,从而不会出现相互干扰的情况。
4.3 为什么执行native方法时,是undefined?
任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的Java方法的JVM指令地址;或者,如果是在执行native方法,则是未指定值(undefined)。为什么?
native 本地方法是大多是通过C实现,并未编译成需要执行的字节码指令,所以在计数器中当然是空(undefined)。说白了,native已经出了虚拟机管控的范围了。