程序计数器(PC寄存器)
概念
程序计数器是一个记录着当前线程所执行的字节码的行号指示器。
程序计数器(Program Counter Register)是一个非常小的空间,可以看作是当前线程所执行的字节码的行号指示器。在虚拟机的概念模型里,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。
特点
如果程序正在执行的是本地(Native)方法,这个计数器的值就为空(Undefined)。native方法是java通过JNI直接调用C/C++库,相当于C/C++暴露给java的一个接口,java调用这个接口就相当于C/C++去执行相应的代码,肯定不会产生相应的字节码,既然没有字节码,那程序计数器不就没得记录。
线程私有,每个线程都存在一个程序计数器。
此内存区域是唯一一个不存在OOM情况的区域。
占用内存非常小,可以忽略不计。
例子
1 | public static void test() { |
反编译后

我是用的idea的Jclasslib插件进行反编译的,也可以使用javap来反编译。
这个类似于行号的就是字节码指令的地址,程序计数器中就是要记录这些地址。
思考
- 为什么使用程序计数器来记录当前线程的执行地址呢?(程序计数器的作用?)
因为CPU需要不停的切换各个线程,这时候CPU切换回需要执行的线程后,就得知道接着从哪开始继续执行。
JVM的字节码解释器需要通过改变程序计数器的值来明确下一条应该执行什么样的字节码指令。
- 程序计数器为什么被设定为线程私有?
JVM的多线程是通过CPU时间片轮转(即线程轮流切换并分配处理器执行时间)算法来实现的。也就是说,某个线程在执行过程中可能会因为时间片耗尽而被挂起,而另一个线程获取到时间片开始执行。当被挂起的线程重新获取到时间片的时候,它要想从被挂起的地方继续执行,就必须知道它上次执行到哪个位置,在JVM中,通过程序计数器来记录某个线程的字节码执行位置。因此,程序计数器是具备线程隔离的特性,也就是说,每个线程工作时都要有属于自己的独立计数器。



