运行时数据区
开始之前,先简单说下运行时数据区,之前的一篇整理关于类加载器的博客也说道了,我们的Java程序首先是通过编译变成字节码文件,然后再由类加载器加载到JVM中。运行时数据区主要分为几个部分,如下图所示:
PC寄存器是里面占用内存很小的一块,运行时数据区中的每一个部分后续我也都会整理相关的博客笔记。
PC寄存器概述
PC寄存器上面也说了,它是运行时数据区中占用内存很小的一部分。它可以看做是当前线程所执行的字节码的行号指示器,它主要用来存储下一条需要执行的字节码指令,是通过执行引擎读取并且去执行。它是程序控制流的指示器,分支,循环,跳转,异常处理,线程恢复等基础功能都要依赖这个计数器来完成。
几个注意点:
- PC寄存器是运行时数据区中占用内存很小的区域,同时也是运行最快的区域。
- 如果当前线程正在执行一个Java方法,那么PC寄存器中存储的就是正在执行的虚拟机字节码指令的地址。如果当前方法是一个本地(native)方法,那么PC寄存器中的值就为空(Undifined)。
- 它是唯一一个在《Java虚拟机规范》中没有规定任何OOM(OutOfMemory)的区域。
PC寄存器使用举例
这边我简单写了一个测试代码,用来简单演示一下。
/**
* pc寄存器测试
*
* @author yuanzhihao
* @since 2021/3/26
*/
public class PCRegisterTest {
public static void main(String[] args) {
int i = 10;
int j = 20;
int k = i + j;
}
}
然后我们对这个类进行编译,编译完成之后我们使用javap命令可以查看生成的字节码文件。
具体执行命令:
javap -v PCRegisterTest.class
左侧这一列就是PC寄存器所存储的指令地址,右侧就是对应的操作指令,这个后续应该也会整理,先不展开。我们的PC寄存器就是保存了这些指令的地址,然后由执行引擎再去取到对应指令地址的对应的操作指令,然后把操作指令翻译成具体的机器指令让CPU去执行。
常见面试题
最后整理两个关于PC寄存器的面试题。
- 为什么使用PC寄存器存储字节码指令?使用PC寄存器存储字节码指令有什么用?
CPU在不停切换线程执行,当前线程执行完后切换线程的时候就需要知道从什么地方再继续执行,这个时候就需要有一个地方存储一下下一条应该执行的字节码的指令。 - 为什么说PC寄存器是线程私有的?
由于Java虚拟机的多线程是通过线程的轮流切换,分配处理器执行的时间来实现的,在任何一个确定的时间,一个处理器只能执行一条线程中的指令。因此为了线程切换之后能够还能正确的恢复到之前执行的位置,每个线程都会单独设置一个PC寄存器,保证各个线程之间不互相影响。
结语以及参考链接
这边是整理的JVM的第二篇笔记博客,工作两年多了,真的开始意识到自己是多么的菜鸡,先定一个小目标,四月份把JVM看完并且整理好完整的博客笔记~
博客中代码地址:https://github.com/yzh19961031/blogDemo/tree/master/jvm
参考地址:
- 尚硅谷JVM全套教程(宋红康详解java虚拟机):https://www.bilibili.com/video/BV1PJ411n7xZ?p=35
- 深入理解Java虚拟机(第3版)