深入理解JVM的PC寄存器(Program Counter Register)

Posted 杀手不太冷!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解JVM的PC寄存器(Program Counter Register)相关的知识,希望对你有一定的参考价值。

深入理解JVM的PC寄存器(Program Counter Register)

PC寄存器概念

作用:PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令。

PC寄存器的流程图,如下图:

1589860597095

1.它是一块很小的内存空间,几乎可以忽略不计。也是运行速度最快的存储区域。

2.在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。

3.任何时间一个线程都只有一个方法在执行,也就是所谓的当前方法。程序计数器会存储当前线程正在执行的Java方法的JVM指令地址;或者,如果是在执行native方法,则是未指定值(undefined);

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

5.字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令。

6.它是唯一一个在Java虚拟就规范中没有规定任何OutOfMemoryError情况的区域。

没有GC和 OOM

用一个程序演示PC寄存器

首先我们编写一个java文件PCRegisterTest.java,如下图:

在这里插入图片描述

然后重新编译PCRegisterTest.java文件,方法:点击菜单栏Build->Recompile “PCRegistertTest.java”,如下图:

在这里插入图片描述

重新编译之后,会在项目的out目录中生成PCRegisterTest.class字节码文件,从上图中可以看到。

接着我们打开一个Terminal终端,执行命令:javap -verbose PCRegisterTest.class对这个字节码文件进行反编译,然后可以查看这个类对应的常量池Constant Pool和寄存器的偏移地址和操作指令等,终端执行指令如下图:

在这里插入图片描述

在这里插入图片描述

反编译命令执行结果,如下图:

在这里插入图片描述

指令地址和操作指令:

在这里插入图片描述

从上图可以看出,执行引擎执行的时候,会根据PC寄存器中的偏移地址,找到下一条要执行的操作指令。

后面的警号加数字,可以定位到Constant Pool常量池的特定位置,如下图:

在这里插入图片描述

在这里插入图片描述

两个常见问题

1.使用PC寄存器存储字节码指令地址有什么用呢?或换种问法:为什么使用PC寄存器记录当前线程的执行地址呢?这俩是同一个问题。

因为CPU需要不停地切换线程,那么在切换回来之后,你就得知道要从哪里继续开始运行,所以,需要用PC寄存器记录一下下一条指令的指令地址,这样当线程切换回来之后,就可以通过寄存器中的指令地址,找到对应的下一条要运行的指令了。

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

首先呢,就是多线程的概念。所谓的多线程就是,有很多个线程,CPU不停地来回切换这些线程,但是CPU切换线程的速度很快,所以我们观察着,就好像是同一时间执行了好多个线程。

所以呢,CPU这样不停地来回切换,它必然会导致某个线程不停地中断恢复,如果PC寄存器不设置成线程私有的,所有的线程共享一个PC寄存器,那么PC寄存器中的指令地址会被覆盖。什么意思呢?加入现在有两个线程,线程1,线程2,其中线程1在执行一半的时候,被CPU切换了,切换到了线程2,此时线程1处于中断状态,它会往PC寄存器里面存储一个指令地址,以便下一次CPU切换到线程1的时候,线程1可以通过PC寄存器里面的指令地址知道它要执行哪条指令。但是呢,当CPU再次切换线程,从线程2切换到线程1,线程2为了下次回来的时候,可以知道要执行哪条指令,它会往PC寄存器里面存储一个指令地址,用来记录下一条指令。如果PC寄存器是所有线程共享的,这个时候就会出现一个问题,什么问题呢?就是,线程2往PC寄存器里面存储的指令地址会覆盖线程1往PC寄存器里面存储的指令地址,这样一来,等到CPU切换到线程1的时候,线程1要执行哪一条指令呢?因为它原本要执行的指令已经被线程2覆盖掉了,所以这样肯定不行。因此,PC寄存器必须要设置成是线程私有的。

扩展:

CPU是怎样切换线程的呢?

使用CPU时间片进行切换的,什么是时间片?就是CPU会给每个线程都分配一段相同的时间,这段时间就叫做时间片。CPU给每个线程分配一个时间片的好处是什么呢?说好处之前,首先要说一下,多线程从宏观上来看,它是很多个线程一起运行的,但是微观角度,CPU每次只能运行一个线程,CPU要不断地切换线程,那这就会产生一个问题,如何保证每个线程执行时间的公平公正呢?其实就是,CPU会给每个线程都分配一个时间片,时间到了,那好,你这个线程别运行了,于是就换下一个线程运行了。

并行并发的区别?

并行就是串行,意思就是同一个时刻只能运行一个进程。

并发:同一时刻可以运行多个进程。

以上是关于深入理解JVM的PC寄存器(Program Counter Register)的主要内容,如果未能解决你的问题,请参考以下文章

JVM 程序寄存器(Program Counter Register)

一文理解JVM的程序计数器(PC)

深入浅出JVM

深入浅出JVM

深入理解JVM2

笔记整理——深入理解JVM原理